溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

黑馬程序員——集合篇

發(fā)布時(shí)間:2020-07-08 14:25:15 來源:網(wǎng)絡(luò) 閱讀:426 作者:optimisticpig 欄目:移動(dòng)開發(fā)

------- android培訓(xùn)、java培訓(xùn)、期待與您交流! ----------

1、集合類

為什么出現(xiàn)集合類?

       面向?qū)ο笳Z言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,所以為了方便對(duì)多個(gè)對(duì)象的操作,就對(duì)對(duì)象進(jìn)行存儲(chǔ),集合就是存儲(chǔ)對(duì)象最常用的一 種方式。

數(shù)組和集合類同是容器,有何不同?

       數(shù)組雖然也可以存儲(chǔ)對(duì)象,但長(zhǎng)度是固定的;集合長(zhǎng)度是可變的。數(shù)組中可以存儲(chǔ)基本數(shù)據(jù)類型,集合只能存儲(chǔ)對(duì)象。

集合類的特點(diǎn)

       集合只用于存儲(chǔ)對(duì)象,集合長(zhǎng)度是可變的,集合可以存儲(chǔ)不同類型的對(duì)象。


2、集合框架的構(gòu)成及分類

黑馬程序員——集合篇

3、Collection接口:

   常用方法:

       1,添加:

       add(object):添加一個(gè)元素

       addAll(Collection) :添加一個(gè)集合中的所有元素。

       2,刪除:

       clear():將集合中的元素全刪除,清空集合。

       remove(obj) :刪除集合中指定的對(duì)象。注意:刪除成功,集合的長(zhǎng)度會(huì)改變。 removeAll(collection) :刪除部分元素。部分元素和傳入Collection一致。

       3,判斷:

       boolean contains(obj) :集合中是否包含指定元素。

       boolean containsAll(Collection) :集合中是否包含指定的多個(gè)元素。 boolean isEmpty():集合中是否有元素。

       4,獲?。?/p>

       int size():集合中有幾個(gè)元素。

       5,取交集:

       boolean  retainAll(Collection) :對(duì)當(dāng)前集合中保留和指定集合中的相同的元素。如果兩個(gè)集合元素相同,返回flase;如果retainAll修改了當(dāng)前集合,返回true。

       6,獲取集合中所有元素:

        Iterator  iterator():迭代器

       7,將集合變成數(shù)組:

        toArray();

4、List接口:元素是有序的,元素可以重復(fù)。因?yàn)樵摷象w系有索引。

常用子類:

       ArrayList:底層的數(shù)據(jù)結(jié)構(gòu)使用的是數(shù)組結(jié)構(gòu)。特點(diǎn):查詢速度很快。但是增刪稍慢。線程不同步。

練習(xí):

import java.util.*;
import java.lang.*;
/*
將自定義對(duì)象作為元素存到ArrayList集合中,并去除重復(fù)元素。
比如:存人對(duì)象。同姓名同年齡,視為同一個(gè)人。為重復(fù)元素。
思路:
1,對(duì)人描述,將數(shù)據(jù)封裝進(jìn)人對(duì)象。
2,定義容器,將人存入。
3,取出。
List判斷元素是否相同,依據(jù)的是元素的equals方法。
*/
class Person
{
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    public boolean equals(Object obj)
    {     
        if (!(obj instanceof Person))
            throw new RuntimeException("類型不匹配");
                                                                                                                                                                                                                                                                                                                                
        Person p = (Person)obj;
        System.out.println(this.name+"===="+p.name);
        return this.name.equals(p.name) && this.age == p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}
class ArrayListTest2
{
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
    public static void main(String[] args)
    {
        ArrayList al = new ArrayList();
        al.add(new Person("zhangsan",34));
        al.add(new Person("zhangsan",34));
        al.add(new Person("lisi",32));
        al.add(new Person("wangwu",24));
        al.add(new Person("wangwu",24));
        al.add(new Person("zhaoliu",23));
        al = singleElement(al);
        for (Iterator it = al.iterator();it.hasNext() ; )
        {
            Person p = (Person)it.next();
            sop(p.getName()+","+p.getAge());
        }
    }
    public static ArrayList singleElement(ArrayList al)
    {
        //定義一個(gè)臨時(shí)容器。
        ArrayList newAl = new ArrayList();
                                                                                                                                                                                                                                                                                                                                
        Iterator it = al.iterator();
        while (it.hasNext())
        {
            Object obj = it.next();
            if (!newAl.contains(obj))//調(diào)用底層方法調(diào)用的是equals方法。所以需要復(fù)寫equals方法。
                newAl.add(obj);
        }
        return newAl;
    }
}

       LinkedList:底層使用的是鏈表數(shù)據(jù)結(jié)構(gòu)。特點(diǎn):增刪速度很快,查詢稍慢。不同步。

相關(guān)練習(xí):

/*
使用LinkedList模擬一個(gè)堆?;蛘哧?duì)列數(shù)據(jù)結(jié)構(gòu)。
堆棧:先進(jìn)后出。如同一個(gè)杯子。
隊(duì)列:先進(jìn)先出。First in First out FIFO 如同一個(gè)水管。
*/
import java.util.*;
class DuiLie
{
    private LinkedList link;
    DuiLie()
    {
        link = new LinkedList();
    }
    public void myAdd(Object obj)
    {
        link.addFirst(obj);
    }
    public void myget()
    {
        return link.removeLast();
    }
    public boolean isNull()
    {
        return link.isEmpty();
    }
}

       Vector:底層是數(shù)組數(shù)據(jù)結(jié)構(gòu)。線程同步。被ArrayList替代了。

相關(guān)練習(xí):

import java.util.*;
/*
枚舉就是Vector特有的取出方式。
發(fā)現(xiàn)枚舉和迭代器很像。
其實(shí)枚舉和迭代時(shí)一樣的。
為什么要設(shè)置枚舉?
因?yàn)槊杜e的名稱以及方法的名稱都過長(zhǎng)。
所以都被迭代器取代了。
枚舉郁郁而終。
*/
class VectorDemo
{
    public static void main(String[] args)
    {
        Vector v = new Vector();
        v.add("java01");
        v.add("java02");
        v.add("java03");
        v.add("java04");
        Enumeration en = v.elements();
        while (en.hasMoreElements())
        {
            System.out.println(en.nextElement());
        }
    }
}


特有方法:

增:

add(index,element);在

addAll(index,Collection):

刪:

remove(index);

改:

set(index,element);

查:

get(index);

subList(form,to);

listIterator();

       List集合特有的迭代器。ListIterator是Iterator的子接口。在迭代時(shí),不可以通過集合對(duì)象的方法操作集合中的元素。因?yàn)闀?huì)發(fā)生ConcurrentModificationException異常。所以,在迭代器時(shí),只能用迭代器的方法操作元素,可是Iterator方法時(shí)有限的。只能對(duì)元素進(jìn)行判斷,取出,刪除的操作。如果要其他操作如添加,修改等,就需要使用其子接口,ListIterator。該接口只能通過List集合的ListIterator方法獲取。


5、Set:元素是無序的,元素不可以重復(fù)。

|--HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表。線程非同步的。

HashSet是如何保證元素的唯一性的呢?

是通過元素的兩個(gè)方法,hashCode和equals來完成。

如果元素的HashCode值相同,才會(huì)判斷equals是否為true。

如果元素的hashCode值不同,不會(huì)調(diào)用equals。

           注意:對(duì)于判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashCode和equals方法。

練習(xí):

/*
往HashSet集合中存入自定義對(duì)象。
姓名和年齡視為同一人。重復(fù)元素。
*/
import java.util.*;
class HashSetTest
{
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
    public static void main(String[] args)
    {
        HashSet hs = new HashSet();
        hs.add(new Person("a1",11));
        hs.add(new Person("a1",11));
        hs.add(new Person("a2",13));
        hs.add(new Person("a3",15));
        //hs.add(new Person("a4",17));
        sop("a1"+hs.contains(new Person("a2",13)));
        sop("a1"+hs.remove(new Person("a3",15)));
                                                                                                                                                                                                                                                                                              
        for (Iterator it = hs.iterator();it.hasNext() ; )
        {
            Person p = (Person)it.next();
            sop(p.getName()+","+p.getAge());
        }
    }
                                                                                                                                                                                                                                                                                              
}
class Person
{
        private String name;
        private int age;
        Person(String name,int age)
        {
            this.name = name;
            this.age = age;
        }
        public int hashCode()
        {
            return name.hashCode()+age;
        }
        public boolean equals(Object obj)
        {
            if (!(obj instanceof Person))
                throw new RuntimeException("數(shù)據(jù)異常");
            Person p = (Person)obj;
            return this.name.equals(p.name) && this.age == p.age;
        }
        public String getName()
        {
            return name;
        }
        public int getAge()
        {
            return age;
        }
}


|--TreeSet:可以對(duì)Set集合中的元素進(jìn)行排序。

記?。号判驎r(shí),當(dāng)注意條件相同時(shí),一定要判斷一下次要條件。

           因?yàn)?span id="uxr3qof" class="Apple-tab-span">底層數(shù)據(jù)結(jié)構(gòu)是二叉樹,保證元素唯一性的依據(jù):compareTo方法return 0;

   TreeSet排序的第一種方式:讓元素自身具備比較性。元素需要實(shí)現(xiàn)Comparable接口,覆蓋compareTo方法。

TreeSet的第二種排序方式。當(dāng)元素自身不具備比較性時(shí),或者具備的比較性不是所需要的。這時(shí)就需要讓集合自身具備比較性。在集合初始化時(shí),就具備比較性。

練習(xí):

/*
練習(xí):按照字符串長(zhǎng)度排序。
字符串本身具備比較性,但是它的比較方式不是所需要的。
*/
import java.util.*;
class TreeSetTest
{
    public static void main(String[] args)
    {
        TreeSet ts = new TreeSet(new StrLenCompare());
        /*匿名內(nèi)部類。
        TreeSet ts = new TreeSet(new Comparator(){
            public int compare(Object o1,Object o2)
            {
                if (!(o1 instanceof String && o2 instanceof String))
                    throw new RuntimeException("類型不匹配");
                                                                                                                                                                                                                                                                                                
                String s1 = (String)o1;
                String s2 = (String)o2;
                                                                                                                                                                                                                                                                                                
                int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
                if (num==0)
                    return s1.compareTo(s2);
                return num;
            }
        });
        */
        ts.add("abcd");
        ts.add("cc");
        ts.add("cba");
        ts.add("aaa");
        ts.add("z");
        ts.add("hahaha");
        for (Iterator it=ts.iterator();it.hasNext() ; )
        {
            System.out.println(it.next());
        }
    }
}
class StrLenCompare implements Comparator
{
    public int compare(Object o1,Object o2)
    {
        if (!(o1 instanceof String && o2 instanceof String))
            throw new RuntimeException("類型不匹配");
                                                                                                                                                                                                                                                                                        
        String s1 = (String)o1;
        String s2 = (String)o2;
                                                                                                                                                                                                                                                                                        
        int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
        if (num==0)
            return s1.compareTo(s2);
        return num;
    }
}

5、Map集合:

   Map集合:該集合存儲(chǔ)鍵值對(duì)。是一對(duì)一對(duì)往里村,要保證鍵的唯一性。

1,添加。

V put(K key, V value)

void putAll(Map<? extends K,? extends V> m)  

2,刪除。

void clear();

V remove(Object key)

3,判斷。

boolean containsKey(Object key)

boolean containsValue(Object value)

boolean isEmpty()  

4,獲取。

V get(Object key)  

int size()  

Collection<V> values()

  5、 重點(diǎn):

   Set<Map.Entry<K,V>> entrySet()

Set<K> keySet()

   常用Map子類:

|--Hashtable:底層是哈希表數(shù)據(jù)結(jié)構(gòu),不可以存入null鍵null值。該集合時(shí)線程同步的。JDK1.0,效率低

|--hashMap:底層是哈希表數(shù)據(jù)結(jié)構(gòu)。允許使用null鍵null值,該集合是不同步的。JDK1.2 效率高。

|--TreeMap:底層是二叉樹數(shù)據(jù)結(jié)構(gòu),線程不同步??梢杂糜诮omap集合中的鍵進(jìn)行排序。

       Map和Set很像。

       其實(shí)Set底層就是使用了Map集合。

   map集合的兩種取出方式。

       1,Set<Map.Entry<k,v>>entrySet:將map集合中的映射關(guān)系存入到了set集合中,而這個(gè)關(guān)系的數(shù)據(jù)類型就是Map.Entry。

       2,Set<K> keySet:將map中所有的鍵存入到Set集合,因?yàn)镾et集合具備迭代器。所以可以迭代方式取出所有的鍵,在根據(jù)get方法。獲取每一個(gè)鍵對(duì)應(yīng)的值。Map集合的取出原理:將map集合轉(zhuǎn)成set集合,在通過迭代器取出。

例子:

import java.util.*;
class MapDemo2
{
    public static void main(String[] args)
    {
        Map<String,String> map = new HashMap<String,String>();
        map.put("02","zhangsan02");
        map.put("05","zhangsan05");
        map.put("03","zhangsan03");
        map.put("01","zhangsan01");
        //將Map集合中的映射關(guān)系取出。存入到Set集合中。
        Set<Map.Entry<String,String>> entrySet = map.entrySet();
                                                                                                                                                                                                                            
        for (Iterator<Map.Entry<String,String>> it = entrySet.iterator();it.hasNext() ; )
        {
            Map.Entry<String,String> me = it.next();
            String key = me.getKey();
            String value = me.getValue();
            System.out.println("key:"+key+"=value:"+value);
        }
        /*
        //先獲取map集合的所有鍵的set集合,keySet();
        Set<String> keySet = map.keySet();
        //有了Set集合,就可以獲取其迭代器。
        Iterator<String> it = keySet.iterator();
        while (it.hasNext())
        {
            String key = it.next();
            //有了鍵就可以通過map集合的get方法獲取其對(duì)應(yīng)的值。
            String value = map.get(key);
            System.out.println("key:"+key+"=value:"+value);
        }
        */
    }
}
/*
Map.Entry 其實(shí)Entry也是一個(gè)接口,它是Map接口中的一個(gè)內(nèi)部接口。
*/
interface Map
{
    public static interface Entry
    {
        public abstract object getKey();
        public abstract object getValue();
    }
}

6、常用工具類


Collections:它的出現(xiàn)給集合操作提供了更多的功能。這個(gè)類不需要?jiǎng)?chuàng)建對(duì)象,內(nèi)部提供的都是靜態(tài)方法。

       靜態(tài)方法:

       Collections.sort(list);//list集合進(jìn)行元素的自然順序排序。

       Collections.sort(list,new ComparatorByLen());///按指定的比較器方法排序。

       class ComparatorByLen implements Comparator<String>{

            public int compare(String s1,String s2){

                int temp = s1.length()-s2.length();

                return temp==0?s1.compareTo(s2):temp;

           }

       }

       Collections.max(list); //返回list中字典順序最大的元素。

       int index = Collections.binarySearch(list,"zz");//二分查找,返回角標(biāo)。

       Collections.reverseOrder();//逆向反轉(zhuǎn)排序。

       Collections.shuffle(list);//隨機(jī)對(duì)list中的元素進(jìn)行位置的置換。

       將非同步集合轉(zhuǎn)成同步集合的方法:

       Collections中的 XXX synchronizedXXX(XXX);

       List synchronizedList(list);

       Map synchronizedMap(map);

       原理:定義一個(gè)類,將集合所有的方法加同一把鎖后返回。

Collection 和 Collections的區(qū)別:

       Collections是個(gè)java.util下的類,是針對(duì)集合類的一個(gè)工具類,提供一系列靜態(tài)方法,實(shí)現(xiàn)對(duì)集合的查找、排序、替換、線程安全化(將非同步的集合轉(zhuǎn)換成同步的)等操作。

        Collection是個(gè)java.util下的接口,它是各種集合結(jié)構(gòu)的父接口,繼承于它的接口主要有Set和List,提供了關(guān)于集合的一些操作,如插入、刪除、判斷一個(gè)元素是否其成員、遍歷等。

-------------------------------------------------------

Arrays:用于操作數(shù)組對(duì)象的工具類,里面都是靜態(tài)方法。

       asList方法:將數(shù)組轉(zhuǎn)換成list集合。

       String[] arr = {"abc","kk","qq"}

       List<String> list = Arrays.asList(arr);//將arr數(shù)組轉(zhuǎn)成list集合。

       將數(shù)組轉(zhuǎn)換成集合,有什么好處呢?用aslist方法,將數(shù)組變成集合;

       可以通過list集合中的方法來操作數(shù)組中的元素:isEmpty()、contains、indexOf、set;

       注意(局限性):數(shù)組是固定長(zhǎng)度,不可以使用集合對(duì)象增加或者刪除等,會(huì)改變數(shù)組長(zhǎng)度的功能方法。比如add、remove、clear。(會(huì)報(bào)不支持操作異常UnsupportedOperationException);

       如果數(shù)組中存儲(chǔ)的引用數(shù)據(jù)類型,直接作為集合的元素可以直接用集合方法操作。

       如果數(shù)組中存儲(chǔ)的是基本數(shù)據(jù)類型,asList會(huì)將數(shù)組實(shí)體作為集合元素存在。

       集合變數(shù)組:用的是Collection接口中的方法:toArray();

       如果給toArray傳遞的指定類型的數(shù)據(jù)長(zhǎng)度小于了集合的size,那么toArray方法,會(huì)自定再創(chuàng)建一個(gè)該類型的數(shù)據(jù),長(zhǎng)度為集合的size。

       如果傳遞的指定的類型的數(shù)組的長(zhǎng)度大于了集合的size,那么toArray方法,就不會(huì)創(chuàng)建新數(shù)組,直接使用該數(shù)組即可,并將集合中的元素存儲(chǔ)到數(shù)組中,其他為存儲(chǔ)元素的位置默認(rèn)值null。

       所以,在傳遞指定類型數(shù)組時(shí),最好的方式就是指定的長(zhǎng)度和size相等的數(shù)組。

       將集合變成數(shù)組后有什么好處?限定了對(duì)集合中的元素進(jìn)行增刪操作,只要獲取這些元素即可。

--------------------------------------------------------------------

System類:

   描述系統(tǒng)一些信息。

   獲取系統(tǒng)屬性信息:Properties getProgerties();

   out:標(biāo)準(zhǔn)輸出:默認(rèn)是控制臺(tái)。

   in:標(biāo)準(zhǔn)輸入,默認(rèn)是鍵盤。

   import java.util.*;

   class SystemDemo

   {

   public static void main(String[] args)

   {

   Properties prop =System.getProperties();

   //因?yàn)镻roperties是Hashtable子類,也就是Map集合的一個(gè)子類對(duì)象。

   //那么可以通過map的方法取出該集合中的元素。

   //該集合中存儲(chǔ)的都是字符串,沒有泛型定義。

   

   //如何在系統(tǒng)中自定義一些特有信息呢?

   System.setProperty("mykey","myvalue");

   //獲取指定屬性信息。

   String value = System.getProperty("os.name");

   System.out.println("value="+value);

   //可不可以在jvm啟動(dòng)時(shí),動(dòng)態(tài)加載一些屬性信息呢?

   //-D<name>=<value>

   String v =System.getProperty("hah");

   System.out.println("v="+v);

   

   /*

   for(Object obj:prop.keySet())

   {

   String value =(String)prop.get(obj);

   System.out.println(obj+"="+value);

   }

   */

   }

   

   }

-----------------------------------------------------------------------

Runtim對(duì)象

   該類并沒有提供構(gòu)造函數(shù)。

   說明不可以new對(duì)象。那么會(huì)直接想到該類的方法都是靜態(tài)的。

   發(fā)現(xiàn)該類中還有非靜態(tài)方法。

   說明該類肯定會(huì)提供了方法獲取本類對(duì)象,而且該方法是靜態(tài)的。并且返回值類型是本類類型。

   由這個(gè)特點(diǎn)可以看出該類使用了單例設(shè)計(jì)模式完成。

   該方法是static Runtime getRuntime();

   */

   class RuntimeDemo

   {

   public static void main(String[] args) throws Exception

   {

   Runtime r = Runtime.getRuntime();

   Process p  = r.exec("notepad.exe SystemDemo.java");//\為轉(zhuǎn)義字符,所以應(yīng)寫為\\

   

   //p.destroy();

   }

   }

------------------------------------------------------------------------

Date對(duì)象

   可以對(duì)時(shí)間的進(jìn)行操作的對(duì)象。

   import java.util.*;

   import java.text.*;

   class DateDemo

   {

   public static void main(String[] args)

   {

   Date d = new Date();

   System.out.println(d);

   //將模式封裝到SimpleDateFormat對(duì)象中。

   SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E kk:mm:ss");

   //調(diào)用format方法,讓模式格式化指定Date對(duì)象。

   System.out.println(sdf.format(d));

   }

   }

-----------------------------------------------------

Calendar對(duì)象

   import java.util.*;

   import java.text.*;

   class CalendarDemo

   {

   public static void main(String[] args)

   {

   Calendar c = Calendar.getInstance();

   

   String[] month = {"一月","二月","三月","四月"

   ,"五月","六月","七月","八月"

   ,"九月","十月","十一月","十二月"};

   

   String[] week ={"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};

   

   int index = c.get(Calendar.MONTH);

   int index1= c.get(Calendar.DAY_OF_WEEK);

   

   sop(c.get(Calendar.YEAR)+"年");

   //sop(c.get((Calendar.MONTH)+1)+"月");

   sop(month[index]);

   

   sop(c.get(Calendar.DAY_OF_MONTH)+"日");

   sop((c.get(Calendar.DAY_OF_WEEK)));

   sop(week[index1]);

   /*

   Date d = new Date();

   SimpleDateFormat sdf = new SimpleDateFormat("yyyy");

   sdf.format(d)

   System.out.println(d);

   */

   }

   public static void sop(Object obj)

   {

   System.out.println(obj);

   }

   }

   

------------------------------------------------------------------------

泛型(Generic)

   泛型:JDK1.5版本以后出現(xiàn)的新特性。用于解決安全問題。是一個(gè)安全機(jī)制。

   好處:

       1,將運(yùn)行時(shí)期出現(xiàn)的問題ClassCastException,轉(zhuǎn)移到了編譯時(shí)期。

       方便于程序員解決問題,讓運(yùn)行時(shí)期問題減少,安全。

       2,避免了強(qiáng)制轉(zhuǎn)換的麻煩。

   泛型格式:通過<>來定義要操作的引用數(shù)據(jù)類型。

   在使用java提供的對(duì)象時(shí),什么時(shí)候?qū)懛盒湍兀?/p>

   通常在集合框架中很常見。

   只要見到<>就要定義泛型。

   其實(shí)<>就是用了接受類型的。

   當(dāng)使用集合時(shí),將集合中要存儲(chǔ)的數(shù)據(jù)類型作為參數(shù)傳遞到<>即可。

class GenericDemo
{
    public static void main(String[] args)
    {
        ArrayList<String> al = new ArrayList<String>();
        al.add("abc01");
        al.add("abc02");
        al.add("abc0991");
        al.add("abc014");
        //al.add(4);
        for (Iterator<String> it=al.iterator();it.hasNext() ; )
        {
            String s = it.next();
            System.out.println(s+":"+s.length());
        }
    }
}

泛型的使用

   1、泛型類

       在類聲明時(shí)通過一個(gè)標(biāo)識(shí)符表示類中某個(gè)字段的類型或者某個(gè)方法的返回值或參數(shù)的類型,這樣在類聲明或?qū)嵗臅r(shí)候只要指定自己需要的類型就ok。

   聲明帶泛型的類:

       class 類名<泛型類型1,泛型類型2……>{

       泛型類型  變量名;

       泛型類型  方法名(){}

       返回值類型 方法名(泛型類型 變量名){}

       }

       使用帶泛型的類:

       類名<具體類> 對(duì)象名 = new 類名<具體類>();

   

   類型參數(shù)規(guī)范:推薦使用規(guī)范-常見的泛型,泛型只保存在源文件中,class文件中不存在;也就是說在編譯階段就會(huì)丟失,基本數(shù)據(jù)類型不能作為泛型類型;

   K鍵,比如映射的鍵  key的類型

   V值,比如Map的值 value類型

   E元素,比如Set<E>  Element表示元素,元素的類型

   T 泛型,Type的意思

   泛型好處:限定添加類型和消除強(qiáng)轉(zhuǎn)轉(zhuǎn)換的麻煩!

   


練習(xí)例子

需求:設(shè)計(jì)一個(gè)表示點(diǎn)的類Point,該類有兩個(gè)字段,一個(gè)是橫坐標(biāo)x,一個(gè)縱坐標(biāo)y,要求坐標(biāo)有3種表達(dá)形式(Integer,Double,String):


如果不使用泛型的話可以新建多個(gè)類,但是內(nèi)部方法體只有參數(shù)類型不一樣,所以用泛型的話更加簡(jiǎn)單,給定一個(gè)占位符,并不明確表示到底是什么類型,在實(shí)際運(yùn)用的時(shí)候才確定類型!!


很好的例子!

package generic;


class Point<T>{

private T t1;

private T t2;

public T getT1() {

return t1;

}

public void setT1(T t1) {

this.t1 = t1;

}

public T getT2() {

return t2;

}

public void setT2(T t2) {

this.t2 = t2;

}

}


public class GenericDemo {

public static void main(String[] args) {

//String 類型的

Point<String> p = new Point<String>();

p.setT1("2");

p.setT2("3");

System.out.println(p.getT1());

System.out.println(p.getT2());

//Integer 類型的

Point<Integer> p2 = new Point<Integer>();

p2.setT1(23);

p2.setT2(24);

System.out.println(p2.getT1());

System.out.println(p2.getT2());

//Double 類型的

Point<Double> p3 = new Point<Double>();

p3.setT1(23.00);

p3.setT2(24.00);

System.out.println(p3.getT1());

System.out.println(p3.getT2());

-----------------------------------------------------------------------------------------------------------------------------------------------

Set<String> s = new HashSet<String>();//創(chuàng)建一個(gè)容器對(duì)象,應(yīng)該在創(chuàng)建的時(shí)候就明確是裝什么的

s.add("a");

//s.add(1);//此時(shí)就加不進(jìn)去了,因?yàn)橐呀?jīng)限制了容器內(nèi)參數(shù)類型!

//此時(shí)就能保證集合里元素類型一致,

Set<Integer> treeSet = new  TreeSet<Integer>();

//規(guī)定key只能是String,value是Date

Map<String,Date> map = new HashMap<String,Date>();

// V put(K key, V value)

Date v = map.put("", new Date());//和上面定義的類型一樣

//V get(Object key)  

Date val = map.get("");

}

}


運(yùn)行結(jié)果

2

3

23

24

23.0

24.0

這樣的話借助泛型一個(gè)類就可以表達(dá)多個(gè)不同類型的參數(shù)!


要求

消除強(qiáng)制類型的轉(zhuǎn)換,如,使用Comparable比較時(shí)每次都需要類型強(qiáng)轉(zhuǎn);


1、沒有加上泛型,最初的需要強(qiáng)制類型轉(zhuǎn)換


package generic;


import java.util.Set;

import java.util.TreeSet;


class Person implements Comparable{//需要進(jìn)行排序的類要實(shí)現(xiàn)Comparable

private Integer age;

public Person(Integer age) {

super();

this.age = age;

}

@Override

public int compareTo(Object o) {

Person p = (Person)o;//強(qiáng)制類型轉(zhuǎn)換

return this.age.compareTo(p.age);

}

public String toString(){

return this.age.toString();

}

}


public class GenericDemo2 {

public static void main(String[] args) {

Set set = new TreeSet();

set.add(new Person(15));

set.add(new Person(12));

set.add(new Person(19));

set.add(new Person(53));

set.add(new Person(62));

System.out.println(set);

}

}

第二步:加上泛型,不再需要強(qiáng)轉(zhuǎn)(因?yàn)轭愋鸵呀?jīng)固定了)!


package generic;


import java.util.Set;

import java.util.TreeSet;


class Person implements Comparable<Person>{//

private Integer age;

public Person(Integer age) {

super();

this.age = age;

}

@Override

public int compareTo(Person o) {

return this.age.compareTo(o.age);//排序

}

public String toString(){

return this.age.toString();

}

}


public class GenericDemo2 {

public static void main(String[] args) {

Set<Person> set = new TreeSet<Person>();

set.add(new Person(15));

set.add(new Person(12));

set.add(new Person(19));

set.add(new Person(53));

set.add(new Person(62));

System.out.println(set);

}

}


2、聲明多個(gè)泛型類型和通配符


若一個(gè)類中多個(gè)字段需要不同的泛型聲明,則在聲明類的時(shí)候指定多個(gè)泛型類型即可;


格式:

public interface IDAO<PK, T> {

PK add(T t);


void remove(PK id);


void update(PK id, T t);


T get(PK id);

}


在進(jìn)行引用傳遞的時(shí)候泛型類型必須匹配才可以傳遞,否則編譯不通過;

使用 ? ,表示未知類型的泛型對(duì)象:

List<?> 表示未知元素的List集合;

這種帶通配符的List僅表示各種泛型List的父類,并不能把元素添加入集合中;

List<?> list = new ArrayList<>(); list.add(1);//ERROR

public void show(List<?> list){}

//表示可接受任意類型的List集合


3、泛型的上限與下限


設(shè)置泛型對(duì)象的上限使用extends,表示參數(shù)類型只能是該類型或該類型的子類:

聲明對(duì)象:類名<? extends 類> 對(duì)象名

定義類:類名<泛型標(biāo)簽 extends 類>{}

設(shè)置泛型對(duì)象的下限使用super,表示參數(shù)類型只能是該類型或該類型的父類:

聲明對(duì)象:類名<? super 類> 對(duì)象名稱

定義類:類名<泛型標(biāo)簽 extends類>{}


public static void  show(List<? extends Number> l){


}

public static void  show(List<? super String> l){


}

public static void show(List<? extends Number> l){}

public static void show(List<? super String> l){}


泛型的上限


public static void main(String[] args) {

Person<Integer> p1 = new Person<>();

p1.setVal(99);

Person<Double> p2 = new Person<>();

p2.setVal(3.14);

Person<String> p3 = new Person<>();

p3.setVal("007");

show(p1);//√

show(p2);//√

show(p3);//×

}

public static void show(Person<? extends Number> p){//此處限定了Person的參數(shù)類型只能是Number或者是其子類,而String并不屬于Number。

System.out.println(p.getVal());

}


泛型的下限


public static void main(String[] args) {

Person<Integer> p1 = new Person<>();

p1.setVal(99);//Integer

Person<Double> p2 = new Person<>();

p2.setVal(3.14);//Double

Person<String> p3 = new Person<>();

p3.setVal("007");//String

Person<Object> p4 = new Person<>();

p4.setVal(new Object());//Object


show(p1);//×

show(p2);//×

show(p3);//√

show(p4);//√

}

public static void show(Person<? super String> p){

System.out.println(p.getVal());

}


很好的例子!

package generic;


import java.util.ArrayList;

import java.util.List;


public class GenericDemo3 {

public static void main(String[] args) {

//因?yàn)閟how方法是用List<?>通配符接收的,所以可以是任意類型!

List<String> l1 = new ArrayList<>();//new ArrayList<String>()

show(l1);

List<Double> l2 = new ArrayList<>();

show(l2);

List<Number> l3 = new ArrayList<>();

show(l3);

List<Object> l4 = new ArrayList<>();

show(l4);

//使用up方法的話接收類型為Number或者其子類

//up(l1);//錯(cuò)誤,因?yàn)閡p方法接收類型為Number或者其子類,l1(String)不符合!

up(l2);

up(l3);

//使用down方法的話接收類型為Number或者其父類

//down(l2);error

down(l3);

down(l4);

}

public static void down(List<? super Number> l){

for (Object object : l) {

System.out.println(object);

}

}

public static void up(List<? extends Number> l){

for (Object object : l) {

System.out.println(object);

}

}

public static void show(List<?> l){

for (Object object : l) {

System.out.println(object);

}

}

}



4、泛型接口和方法


java5后,可以聲明泛型接口,聲明方式和聲明泛型類是一樣的。

public interface IDAO<T>{}

泛型接口子類有兩種方式:

直接在子類后申明泛型;




向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI