Java學(xué)習(xí)之集合框架

一、集合框架的概述

1、概述:

1、簡述:
所謂集合,就是為方便對多個對象的操作,對對象進(jìn)行存儲。集合就是存儲對象最常用的一種方式。

2、集合與數(shù)組的區(qū)別:
數(shù)組:可存儲同種類型的數(shù)據(jù),但長度固定,也可存儲基本類型的數(shù)據(jù)
集合:只可存儲對象,長度可變,類型可以不同。

3、集合的特點:
只用于存儲對象,長度可變,也可存不同類型的對象。
集合是一個接口,將每種容器的共性提取,形成的一個體系。

4、數(shù)據(jù)結(jié)構(gòu):
由于每種容器對數(shù)據(jù)的存儲方式都各不相同,所以出現(xiàn)了不同的容器。此種存儲方式稱之為數(shù)據(jù)結(jié)構(gòu)。

2、集合體系如圖:

集合體系示意圖

3、集合中的共性方法:

下面從增刪改查等方面對這些共性發(fā)方法進(jìn)行簡單介紹:
說明:
a.add方法中的參數(shù)類型是Object,以便于接收任意類型的對象
b.集合中存儲的都是對象的引用(即地址)。

1、增加:
add(Object obj); -----> 添加元素

2、刪除:
remove(); -----> 刪除集合中指定參數(shù)的元素
removeAll(); -----> 刪除當(dāng)前集合中與另一集合相同的元素,即只保留與另一集合不同的元素
clear(); -----> 清空集合中的元素,集合還存在

3、獲取集合長度:
size(); -----> 獲取集合長度,即集合元素的個數(shù)

4、修改:
set(int index,e); -----> 將指定位置(index)上的元素修改為給定的參數(shù)e

5、判斷:
boolean contains(e); -----> 判斷給定元素e是否存在于集合中

6、迭代器:
iterator(); -----> 集合取出元素的方式
boolean hasNext(); -----> 判斷是否還有下一個元素
next(); -----> 取出下一個元素

示例:

import java.util.*;  
  
class CollectionDemo   
{  
    public static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
      
    public static void main(String[] args)   
    {  
        base_method();  
        sop("------------------");  
        method2();  
        sop("------------------");  
        method_get();  
    }  
      
    public static void base_method()  
    {  
        //創(chuàng)建一個集合容器,使用Collection接口的子類,ArrayList  
        ArrayList al = new ArrayList();  
        //1.添加元素--->add(Object obj),多態(tài)   
        al.add("java01");  
        al.add("java02");  
        al.add("java03");  
        al.add("java04");  
  
        //打印原集合  
        sop("原集合" + al);  
  
        //3.刪除元素  
        al.remove("java02");  
          
        //清空集合中的元素  
        al.clear();  
  
        //4.判斷元素  
        //判斷集合中是否存在某個元素:contains()  
        sop("是否存在java03:" + al.contains("java03"));  
        //判斷集合是否為空:isEmpty()  
        sop("判斷集合是否為空:" + al.isEmpty());  
  
  
        //2.獲取個數(shù),集合長度  
        sop("size :" + al.size());  
  
        //打印改變后集合  
        sop(al);  
  
  
        System.out.println("Hello World!");  
    }  
  
    public static void method2()  
    {  
        //創(chuàng)建另一個新集合  
        ArrayList at1 = new ArrayList();  
        at1.add("java01");  
        at1.add("java02");  
        at1.add("java03");  
        at1.add("java04");  
  
        //打印原集合  
        sop("原集合at1:" + at1);  
  
        ArrayList at2 = new ArrayList();  
        at2.add("java01");  
        at2.add("java02");  
        at2.add("java05");  
        at2.add("java06");  
        sop("原集合at2:" + at2);  
  
        //removeAll()--->只保留和at2不相同的元素。  
        at1.removeAll(at2);  
        sop("remove后at1:" + at1);  
        sop("now集合at2:" + at2);  
  
  
        //取兩個集合的交集,at1中只保留交集的部分  
        at1.retainAll(at2);  
          
        sop("取完交集后的at1:" + at1);  
    }  
  
    public static void method_get()  
    {  
        //創(chuàng)建另一個新集合  
        ArrayList at1 = new ArrayList();  
        at1.add("java01");  
        at1.add("java02");  
        at1.add("java03");  
        at1.add("java04");  
  
        //打印原集合  
        sop("原集合at1:" + at1);  
  
        //獲取迭代器,用于去除集合中的元素  
        Iterator it = at1.iterator();  
  
        while (it.hasNext())  
        {  
            sop(it.next());  
        }  
    }  
}

4、Collection接口包含的子類

Collection接口包含List與Set等子類
List:元素是有序的,元素可重復(fù),因該集合體系有索引
Set:元素是無序的,元素不可重復(fù)

下面具體總結(jié)一下關(guān)于兩種集合:

二、List集合

1、概述:

List集合包含三個子類:ArrayList、LinkedList以及Vector等。
具體區(qū)別如下:
1、ArrayList:底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組結(jié)構(gòu)
特點:查詢速度很快,因為有索引(角標(biāo)),但增刪速度稍慢。是線程不同步的。

2、LinkedList:底層使用的是鏈表數(shù)據(jù)結(jié)構(gòu)
特點:增刪速度很快,但查詢速度稍慢,因為每一個元素都鏈接到前一元素。

3、Vector:底層是數(shù)組結(jié)構(gòu),JDK1.0出現(xiàn),比較老。
特點:增刪查詢都很慢,被ArrayList替代了,線程是同步的。

2、對于List集合特有的方法:

凡是可操作角標(biāo)的方法都是該體系特有的方法,基本方法和Collection中的一樣。
1、增加:
add(int index,e); -----> 在指定位置增加給定的元素
addAll(int index,Collection); -----> 在指定位置增加給定集合中的所有元素,若省略位置參數(shù),則在當(dāng)前集合的后面依次添加元素

2、刪除:
remove(int index); -----> 刪除集合中指定位置上的元素

3、修改:
set(int index,e); -----> 將指定位置(index)上的元素修改為給定的參數(shù)e

4、查詢:
get(int index); -----> 獲取指定位置上的元素
indexOf(e); -----> 通過指定元素獲取其在集合中的位置
subList(int from,int to); -----> 獲取從from到to位置上的元素
Iterator listIterator(); -----> 返回Iterator接口類型值

注:
1、listIterator是List特有的迭代器,是Iterator子接口。在迭代時,不可通過集合對象的方法操作集合中的元素,因為會發(fā)生ConcurrentModficationException異常。
所以,在迭代時,只能用迭代器的方法操作,可Iterator方法是有限的,若想要其他操作如增刪改寫等,就需要使用子接口,即ListIterator,該接口只能通過List集合的listIerator方法獲取。

2、在迭代時,循環(huán)中的next()調(diào)用一次,就要對hasNext判斷一次,不可判斷一次調(diào)用兩次。

3、List集合判斷元素是否相同,一句的是元素的equals方法,其中,contains中就是調(diào)用的equals方法。

示例:

import java.util.*;  
class ListDemo   
{  
    public static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
      
    public static void main(String[] args)   
    {  
        methodAdd();  
        //methodListIterator();  
    }  
  
    public static void methodAdd()  
    {  
        //創(chuàng)建一個集合容器,使用Collection接口的子類,ArrayList  
        ArrayList list = new ArrayList();  
        //1.添加元素--->add(Object obj),多態(tài)   
        list.add("java01");  
        list.add("java02");  
        list.add("java03");  
        list.add("java04");  
  
        ArrayList list2 = new ArrayList();  
        //1.添加元素--->add(Object obj),多態(tài)   
        list2.add("java05");  
        list2.add("java06");  
        list2.add("java07");  
        list2.add("java08");  
  
        //打印原集合  
        sop("原集合:" + list);  
        sop("------------------");  
  
        //1.在某一個位置上添加元素:add(int index,"新元素")  
        list.add(1,"java001");  
        sop("增加后的集合:" + list);  
        sop("---------");  
        list.addAll(1,list2);  
        sop("在list中1位置后添加list2:" + list);  
        sop("------------------");  
  
        //2.刪除指定位置上的元素:  
        list.remove(2);  
        sop("刪除后的集合:" + list);  
        sop("------------------");  
  
        //3.改變某一位置上的元素:set(int index,"要改成的元素")  
        list.set(2,"java007");  
        sop("改變角標(biāo)為2的元素后的元素:" + list);  
        sop("------------------");  
  
        //4.獲取元素:get()  
        list.get(1);  
        sop("獲取角標(biāo)為1上的元素:" + list.get(1));  
        sop("------------------");  
  
        //通過某個元素獲取其在集合中的位置--indexOf("查找的元素")  
        int m = list.indexOf("java007");  
        sop("獲取“java007”所在的位置:" + m);  
  
        //獲取從某個位置到另一位置上的元素subList()  
        List l = list.subList(1,3);  
        sop("獲取從位置1到3上的元素:" + l);  
        sop("------------------");  
  
        //4.獲取全部元素  
        //get方法的for循環(huán)  
        sop("get方法:");  
        for (int i=0;i<list.size();i++)  
        {  
            sop("list(" + i + ")" + list.get(i));  
        }  
        sop("------------------");  
  
        //迭代器方法:Iterator()  
        for (Iterator it = list.iterator();it.hasNext(); )  
        {  
            sop("next:" + it.next());  
        }  
        sop("------------------");  
}  
  
    public static void methodListIterator()  
    {  
        //演示列表迭代器:  
        ArrayList list = new ArrayList();  
        //1.添加元素--->add(Object obj),多態(tài)   
        list.add("java01");  
        list.add("java02");  
        list.add("java03");  
        list.add("java04");  
  
        //打印原集合  
        sop("原集合:" + list);  
        sop("------------------");  
  
          
  
        //在迭代過程中,準(zhǔn)備添加或刪除元素  
        for (ListIterator it = list.listIterator();it.hasNext(); )  
        {  
            Object obj = it.next();  
            if (obj.equals("java01"))  
                it.remove();  
            else if(obj.equals("java02"))  
                it.add("增加java200");  
            else if(obj.equals("java03"))  
                it.set("修改為java300");  
            sop("obj:" + obj);  
        }  
        sop("list :" + list);  
    }  
}

3、Vector類:

Vector中有種特殊的取出方式,即為枚舉
1、枚舉和迭代器十分相似,其實兩者是一樣的,由于枚舉的名稱以及方法名都過長,因此,就被迭代器取代了。這里就不過多的介紹了。

4、LinkedList類特有方法:

一)JDK1.6之前的方法
1、增加:
addFirst(obj); -----> 在集合頭部添加給定的元素
addLast(obj); -----> 在集合尾部添加給定的元素

2、獲取:
getFirst(); -----> 獲取集合第一個元素,若集合中沒有元素,則出現(xiàn)NoSuchElementException
getLast(); -----> 獲取集合最后一個元素,若集合中沒有元素,則出現(xiàn)NoSuchElementException

3、刪除:
removeFirst(); -----> 獲取并刪除集合第一個元素,若集合中沒有元素,則出現(xiàn)NoSuchElementException
removeLast(); -----> 獲取并刪除集合最后一個元素,若集合中沒有元素,則出現(xiàn)NoSuchElementException

二)JDK1.6出現(xiàn)的替代方法:
1、增加:
offerFirst(obj); -----> 在集合頭部添加給定的元素
offerLast(obj);``` -----> 在集合尾部添加給定的元素

2、獲取:
peekFirst(); -----> 獲取集合第一個元素,若集合中沒有元素,則返回null
peekLast(); -----> 獲取集合最后一個元素,若集合中沒有元素,則返回null

3、刪除:
pollFirst(); -----> 獲取并刪除集合第一個元素 ,若集合中沒有元素,則返回null
pollLast(); -----> 獲取并刪除集合最后一個元素,若集合中沒有元素,則返回null

三、Set 集合

1、概述:

1、Set集合的特點:
1)集合中的元素師無需的(存入和取出的順序不一定一致),且元素不可重復(fù)。
2)Set集合的功能和Collection集合的是一樣的,并沒有什么特別的方法。

這里主要說一下關(guān)于HashSet和TreeSet兩種集合的方法和特點:

2、HashSet類

1、特點:
底層數(shù)據(jù)結(jié)構(gòu)時哈希表,且元素取出方式只有迭代器方法

2、哈希表簡介:
1)哈希表是按照哈希值的大小進(jìn)行排列的,如果兩個哈希值不同,則大的值放后面;如果兩個哈希值相同,則再用equals方法比較兩個元素的對象是否相同,如果不同,則將第二個值順延,兩個值串起來,放在同一個位置上。

2)取值時是按照哈希值取出來的。

3)哈希值的取值方式:哈希值存入哈希表中,哈希表也稱散列表。散列表是存放記錄的數(shù)組。具體來說,散列表是根據(jù)散列函數(shù)H(Key)和處理沖突的方法將一組關(guān)鍵字映象到一個有限的連續(xù)的地址集(區(qū)間)上,并以關(guān)鍵字在地址集中的“象”,作為這條記錄在表中的存儲位置,這種表表稱為散列表,這一映象過程就稱為散列造表或散列,所存儲位置稱為散列地址(這是百度百科上的內(nèi)容)。我的理解是:存入的對象的地址是通過提取其信息摘要,通過散列函數(shù)計算而獲得的一個關(guān)鍵碼(Key)即哈希值,然后將這個值存入哈希表,而哈希表的存值方式是按照哈希值的大小順序存儲的,并且在這個哈希表中有自己的索引,但是哈希表的取值方式并不是按照索引的方式取出的。取出方式是按照哈希表中特有的算法取出的哈希值(注意,現(xiàn)在說的是哈希值,不是元素的取出),這些算法有直接尋址法、折疊法、平方取中法以及其他的一些方法等等。具體是按哪種算法查找的,我并不太清楚,所以,取出的哈希值可能就不是按照哈希值的大小順序取出的了。

3、HashSet如何保證元素的唯一性:
通過元素的兩個方法hasCode和equals方法來完成的。
如果元素的hashCode的值相同,才會判斷equals是否為true。如果元素的hashCode值不相同,就不會調(diào)用equals方法了。
注:
對于判斷元素是否存在和刪除(或添加)。依賴的方法是元素的hashcode和equals方法。

示例:

/* 
 
思路: 
    1、對人描述,將數(shù)據(jù)封裝進(jìn)對象 
    2、定義容器,將人存入 
    3、取出 
    4、移除 
*/  
  
import java.util.*;  
  
class TypeException extends Exception  
{  
    TypeException(String message)  
    {  
        super(message);  
    }  
}  
class Person  
{  
    private String name;  
    private int age;  
    Person(String name,int age)  
    {  
        this.name = name;  
        this.age = age;  
    }  
    public String getName()  
    {  
        return name;  
    }  
    public int getAge()  
    {  
        return age;  
    }  
    public int hashCode()  
    {  
        return this.name.hashCode()+age*39;  
    }  
    public boolean equals(Object obj)  
    {  
        try  
        {  
            if (!(obj instanceof Person))  
                throw new TypeException("NoSuchTypeException");  
        }  
        catch (TypeException e)  
        {  
            System.out.println(e.toString());  
        }  
        Person p = (Person)obj;  
        return this.name.equals(p.name) && this.age == p.age;  
    }  
}  
class HashDemo   
{  
    public static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
  
    public static void printE(HashSet hs)  
    {  
        Iterator it = hs.iterator();  
  
        while (it.hasNext())  
        {  
            Person p = (Person)it.next();  
            sop(p.getName() + "--" + p.getAge());  
        }  
    }  
  
    public static void main(String[] args)   
    {  
        HashSet hs = new HashSet();  
        hs.add(new Person("a1",11));  
        hs.add(new Person("a2",12));  
        hs.add(new Person("a3",13));  
        hs.add(new Person("a2",12));  
        hs.add(new Person("a3",13));  
        sop("原集合:");  
        printE(hs);  
        sop("移除后的集合:");  
        hs.remove(new Person("a3",13));  
        printE(hs);  
    }  
}

3、TreeSet類:

1、特點:
1)底層的數(shù)據(jù)結(jié)構(gòu)為二叉樹結(jié)構(gòu)(紅黑樹結(jié)構(gòu))

2)可對Set集合中的元素進(jìn)行排序,是因為:TreeSet類實現(xiàn)了Comparable接口,該接口強(qiáng)制讓增加到集合中的對象進(jìn)行了比較,需要復(fù)寫compareTo方法,才能讓對象按指定需求(如人的年齡大小比較等)進(jìn)行排序,并加入集合。
java中的很多類都具備比較性,其實就是實現(xiàn)了Comparable接口。

注意:排序時,當(dāng)主要條件相同時,按次要條件排序。

3)二叉樹示意圖:
我通過對二叉樹分布的測驗,畫了一個圖,不知對否,僅供參考
對于存入時每個元素的比較,并不是連續(xù)排下來的,而是隨著元素的個數(shù)而改變的,如圖中所示:
第①步:22比較完了,如圖①,之后會重新分布
第②部:以22為頂部,開始比較,如圖②
第③步:比完第一個33后的圖示,當(dāng)比第二個33重復(fù)元素的時候,又重新分布了
第④步:分布如圖,第二個33是按這個如比較的。


二叉樹示意圖

2、保證元素唯一性的依據(jù):
實現(xiàn)的compareTo方法的返回值,是正整數(shù)、負(fù)整數(shù)或零,則兩個對象較大、較小或相同。相等時則不會存入。

3、兩種比較方式:
排序有兩個要素:元素和集合
1)第一種排序方式:自然排序
讓元素自身具備比較性。元素需要實現(xiàn)Comparable接口,覆蓋compareTo方法,這種方式也稱為元素的自然排序或默認(rèn)排序方式。

示例:

/* 
第一種排序方式:自然排序,實現(xiàn)Comparable接口,重寫compareTo方法 
需求: 
向TreeSet集合中存儲自定義對象學(xué)生 
按照學(xué)生的年齡進(jìn)行排序 
*/  
import java.util.*;  
//此接口強(qiáng)制讓Student實現(xiàn)比較性  
class Student implements Comparable   
{  
    //定義Student私有屬性  
    private String name;  
    private int age;  
    //構(gòu)造Student函數(shù),初始化  
    Student(String name,int age)  
    {  
        this.name = name;  
        this.age = age;  
    }  
    //公共訪問方法,訪問私有屬性  
    public String getName()  
    {  
        return name;      
    }  
    public int getAge()  
    {  
        return age;  
    }  
    //復(fù)寫Comparator中的compare方法,自定義比較器  
    public int compareTo(Object obj)  
    {  
        //判斷是否屬于Student類型,否則拋異常  
        if (!(obj instanceof Student))  
            throw new RuntimeException("NotSuchTypeException");  
        //將Object類對象強(qiáng)轉(zhuǎn)為Student類  
        Student s = (Student)obj;  
          
        //System.out.println(this.age + "--compare-" + s.age);//測試用,查看比較情況  
  
        //按年齡大小比較,相同則比較姓名大小,不同返回兩年齡之差  
        if (this.age == s.age)  
        {  
            return this.name.compareTo(s.name);  
        }  
        else if (this.age <s.age)  
            return this.age-s.age;  
        return this.age-s.age;  
    }  
    /* 
    //如果按照存入順序輸出 
    public int compareTo() 
    { 
        return 1;//改為-1則按倒敘輸出 
    } 
    */  
}  
//測試  
class TreeSetTest  
{  
    public static void main(String[] args)   
    {  
        //創(chuàng)建集合,并添加元素  
        TreeSet ts = new TreeSet();  
        ts.add(new Student("li01",25));  
        ts.add(new Student("li02",20));  
        ts.add(new Student("li01",22));  
        ts.add(new Student("li05",24));  
        ts.add(new Student("li08",40));  
        //打印集合中元素  
        printE(ts);  
          
        System.out.println("Hello World!");  
    }  
  
    //定義打印集合中元素的功能  
    public static void printE(TreeSet ts)  
    {  
        //迭代器方法獲取  
        Iterator it = ts.iterator();  
      
        while (it.hasNext())  
        {  
            //將返回的元素(Object類)強(qiáng)轉(zhuǎn)為Student類  
            Student s = (Student)it.next();  
            System.out.println(s.getName() + "---" + s.getAge());  
        }  
    }  
}

2)第二種排序方式:比較器
當(dāng)元素自身不具備比較性是,或者具備比較性,卻不是所需要的,這時就需要讓集合自身具備比較性。在集合初始化時就有了比較方式(即參閱構(gòu)造函數(shù))。
當(dāng)兩種排序方式都存在時,以比較器為主。

如何構(gòu)造比較器:定義一個類,實現(xiàn)Comparator接口,覆蓋compare方法。

注:字符串本身具備比較性,但是它的比較方式可能不是所需要的,這時,就只能使用比較器了。

示例:

import java.util.*;  
//此接口強(qiáng)制讓Student實現(xiàn)比較性  
class Student implements Comparable  
{  
    //定義Student私有屬性  
    private String name;  
    private int age;  
    //構(gòu)造Student函數(shù),初始化  
    Student(String name,int age)  
    {  
        this.name = name;  
        this.age = age;  
    }  
    //公共訪問方法,訪問私有屬性  
    public String getName()  
    {  
        return name;  
    }  
    public int getAge()  
    {  
        return age;  
    }  
  
    //復(fù)寫Comparator中的compare方法,自定義比較器  
    public int compareTo(Object obj)  
    {  
        //判斷是否屬于Student類型,否則拋異常  
        if (!(obj instanceof Student))  
            throw new RuntimeException("NotSuchTypeException");  
        //按年齡大小比較,相同則比較姓名大小,不同返回兩年齡之差  
        Student s = (Student)obj;  
        if (this.age > s.age)  
            return this.age-s.age;  
        else if (this.age == s.age)  
        {  
            return this.name.compareTo(s.name);  
        }  
        return this.age-s.age;  
    }  
          
}  
  
//定義比較器,實現(xiàn)Comparator接口  
class MyCompare implements Comparator  
{  
    //重寫Comparator中的compare方法,按姓名順序排序  
    public int compare(Object o1,Object o2)  
    {  
        //判斷給定對象是否為Student類,否則拋異常  
        if (!((o1 instanceof Student) && (o2 instanceof Student)))  
            throw new RuntimeException("NotSuchTypeException");  
        //將給定對象強(qiáng)轉(zhuǎn)為Student類  
        Student s1 = (Student)o1;  
        Student s2 = (Student)o2;  
        //比較名字,返回數(shù)值,相同則比較年齡  
        int n = s1.getName().compareTo(s2.getName());  
        if (n == 0)  
            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));  
        return n;  
    }  
}  
//測試  
class TreeSetComDemo   
{  
    public static void main(String[] args)   
    {  
        //TreeSet ts = new TreeSet();  
  
        //創(chuàng)建集合,加入接口類參數(shù),并添加元素  
        TreeSet ts = new TreeSet(new MyCompare());  
        ts.add(new Student("li01",25));  
        ts.add(new Student("li02",20));  
        ts.add(new Student("li01",22));  
        ts.add(new Student("li05",24));  
        ts.add(new Student("li08",40));  
  
        //打印集合中元素  
        printE(ts);  
    }  
      
    //定義打印集合中元素的功能  
    public static void printE(TreeSet ts)  
    {  
        //迭代器方法獲取  
        Iterator it = ts.iterator();  
      
        while (it.hasNext())  
        {  
            //將返回的元素(Object類)強(qiáng)轉(zhuǎn)為Student類  
            Student s = (Student)it.next();  
            System.out.println(s.getName() + "---" + s.getAge());  
        }  
    }  
}

四、Map 集合

1、概述:

1、簡述:
Map<K,V>集合是一個接口,和List集合及Set集合不同的是,它是雙列集合,并且可以給對象加上名字,即鍵(Key)

2、特點:
1)該集合存儲鍵值對,一對一對往里存
2)要保證鍵的唯一性。

2、方法簡介:

Map集合中的方法和上面集合的方法是很相似的,這里不一一都具體說明了,用示例的形式體現(xiàn)一下:
1、添加: 添加單個元素:put(k key,V value); 添加一個集合:putAll(Map<? extends K,? extends V> m)

2、刪除: 獲取并移除:remove(Object key); 清空集合中元素:clear (Object key)

3、判斷: 判斷集合是否為空: isEmpty() ; 鍵對應(yīng)的值是否存在:containsKey(Object key); 值對應(yīng)的鍵是否存在:containsValue(Object obj) ----> 返回boolean類型

4、獲取: 獲取單個元素:get(Object key); 獲取長度:size(); 獲取Map集合中的所有值(value),返回Conllection集合。

注:
a.也可以通過get()方法的返回值來判斷一個鍵是否存在,通過返回null來判斷。
b.其中put方法:如果出現(xiàn)添加相同的鍵,那么后添加的值會覆蓋原有鍵對應(yīng)的值,并且該方法返回被覆蓋的值即原值。

示例:

/* 
Map集合方法 
*/  
import java.util.*;  
class MapDemo   
{  
    public static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
    public static void main(String[] args)   
    {  
        //創(chuàng)建Map集合,并添加元素  
        Map<Integer,String> map = new HashMap<Integer,String>();  
        map.put(1,"zhangsan");  
        map.put(2,"lisi");  
        map.put(3,"wangwu");  
        map.put(4,"heihei");  
        map.put(5,"xixi");  
        //獲取長度  
        int n = map.size();  
        //打印元素  
        sop("原集合:" + map + "\n長度為:" + n);  
        sop("---------------------------------------");  
        //創(chuàng)建新集合,并添加元素  
        Map<Integer,String> m = new HashMap<Integer,String>();  
        m.put(7,"zann");  
        m.put(9,"hewi");  
        m.put(13,"wangfei");  
        m.put(14,"huxi");  
        m.put(10,"anch");  
        //用putAll將元素添加到原集合中  
        map.putAll(m);  
        sop("putAll --新集合:" + map);  
        sop("----------------------------------");  
        //刪除元素  
        sop("remove:" + map.remove(01));  
        sop("新集合:" + map);  
        sop("----------------------------------");  
        /* 
        //清空集合中的元素 
        map.clear(); 
        sop("新集合:" + map); 
        //判斷是否為空集合 
        boolean be = map.isEmpty(); 
        sop("isEmpty ,null? :" + be); 
        sop("----------------------------------"); 
        */  
  
        //判斷元素是否存在  
        boolean bk = map.containsKey(01);  
        boolean bv = map.containsValue("wangwu");  
        sop("判斷:\n01?:" + bk + "-----  wangwu?:" + bv);  
        sop("----------------------------------");  
          
        //獲取元素:get  
        String s = map.get(01);  
        String s1 = map.get(02);  
        //Integer i =  map.get("lisi");  
        //Integer i2 = map.get("zhangsan");  
        sop(map.get("lisi"));  
        sop(map.get("zhangsan"));   
        sop("獲取元素get:01:" + s + ",02:" + s1);  
        sop("-----------------------------------------------");  
        //獲取集合中的所有元素:Value  
        Collection<String>  coll = map.values();  
        sop("value--獲取集合中所有元素:" + coll);  
        sop("----------------------------------");  
    }  
}

3、Map集合中的子類:

1、HashTable:特點 -- > 底層是哈希表數(shù)據(jù)結(jié)構(gòu),不可存入null鍵和null值。該集合是線程同步的,效率較低

2、HashMap:特點 -- > 底層是哈希表數(shù)據(jù)結(jié)構(gòu),允許使用null值和null鍵。該集合是線程同步的,效率較高

3、TreeMap:特點 -- > 底層是二叉樹數(shù)據(jù)結(jié)構(gòu),線程不同步,可以用于給Map集合中的鍵值進(jìn)行排序,和Set很像,其實,Set集合的底層就是使用了Map集合。

4、兩種獲取集合元素的方法:

重點說一下獲取方法中的兩個:keySet()和entrySet()方法

1、keySet()方法獲取元素
原理:將Map集合中的所有鍵存入到Set集合中,因為Set集合具備迭代器,所以可以用迭代方式取出所有的鍵,再根據(jù)get方法獲取每一個鍵對應(yīng)的值。
簡單說就是:Map集合---->Set集合 ---->迭代器取出

示例:

//keySet集合測試  
  
import java.util.*;  
class KeySetDemo   
{  
    public static void main(String[] args)   
    {  
        //創(chuàng)建Map集合,并添加元素  
        Map<Integer,String> map = new HashMap<Integer,String>();  
        map.put(2,"zhangsan");  
        map.put(6,"lisi");  
        map.put(3,"wangwu");  
        map.put(4,"heihei");  
        map.put(5,"xixi");  
        //獲取map集合中的所有鍵的Set集合  
        Set<Integer> keySet = map.keySet();  
        //有了Set集合就可以獲取其迭代器,取值  
        Iterator<Integer> it = keySet.iterator();  
        while (it.hasNext())  
        {  
            Integer i = it.next();  
            String s = map.get(i);  
            System.out.println(i + " = " + s);  
        }  
    }  
}

2、entrySet()方法獲取元素:
原理:
將Map集合中的映射關(guān)系存入到了Set集合中,而這個映射關(guān)系的數(shù)據(jù)類型是Map.Entry,在通過迭代器將映射關(guān)系存入到Map.Entry集合中,并通過其中的getKey()和getValue()放取出鍵值。

示例:

/* 
entrySet取出方式: 
*/  
import java.util.*;  
class EntrySetDemo  
{  
    public static void main(String[] args)   
    {  
        //創(chuàng)建集合,存入元素  
        Map<String,String> map = new HashMap<String,String>();  
        map.put("01","lisi1");  
        map.put("02","lisi2");  
        map.put("03","lisi3");  
        map.put("04","lisi4");  
        //獲取map集合中的所有鍵,存入到Set集合中,  
        Set<Map.Entry<String,String>> entry = map.entrySet();  
        //通過迭代器取出map中的鍵值關(guān)系,迭代器接收的泛型參數(shù)應(yīng)和Set接收的一致  
        Iterator<Map.Entry<String,String>> it = entry.iterator();  
        while (it.hasNext())  
        {  
            //將鍵值關(guān)系取出存入Map.Entry這個映射關(guān)系集合接口中  
            Map.Entry<String,String>  me = it.next();  
            //使用Map.Entry中的方法獲取鍵和值  
            String key = me.getKey();  
            String value = me.getValue();  
            System.out.println(key + " : " + value);  
        }  
    }  
}

補充:關(guān)于Map.Entry
Map是一個接口,其實,Entry也是一個接口,它是Map的子接口中的一個內(nèi)部接口,就相當(dāng)于是類中有內(nèi)部類一樣。為何要定義在其內(nèi)部呢?

原因:
a.Map集合中村的是映射關(guān)系這樣的兩個數(shù)據(jù),是先有Map這個集合,才可有映射關(guān)系的存在,而且此類關(guān)系是集合的內(nèi)部事務(wù)。
b.并且這個映射關(guān)系可以直接訪問Map集合中的內(nèi)部成員,所以定義在內(nèi)部。

5、Map集合的應(yīng)用及擴(kuò)展:

1、何時使用Map集合:當(dāng)量數(shù)據(jù)之間存在著映射關(guān)系的時候,就應(yīng)該想到使用Map集合。

2、示例:
獲取該字符串中的字母出現(xiàn)的次數(shù),如:"sjokafjoilnvoaxllvkasjdfns";希望打印的結(jié)果是:a(3)c(0).....
通過結(jié)果發(fā)現(xiàn),每個字母都有對應(yīng)的次數(shù),說明字母和次數(shù)之間有映射關(guān)系。

測試如下:

import java.util.*;  
class MapTest  
{  
    public static void main(String[] args)   
    {  
        String s = "abcsjokafjoilnvoaxllvkasjdfnsde 0[fga8/-abbdc";  
        String str = LetterNum(s);  
        System.out.println(str);  
    }  
  
    public static String LetterNum(String str)  
    {  
        //將字符串轉(zhuǎn)換成字符數(shù)組,因為對每個字母進(jìn)行操作  
        char[] ch = str.toCharArray();  
        //定義一個Map集合,因為打印結(jié)果的字母有順序,所以使用TreeMap集合  
        TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();  
        int count = 0;  
        //遍歷字符數(shù)組,將每一個字母作為鍵去查map集合,  
        for (int i=0;i<ch.length;i++)  
        {  
            //判斷集合是否含有其他非字母,是則再次循環(huán)  
            if (!(ch[i]>= 'a' && ch[i] <= 'z' || ch[i] >= 'A' && ch[i] <= 'Z'))  
                continue;  
            //取出鍵對應(yīng)的值,不為則計數(shù)器加1,存入集合,并將計數(shù)器清零,用于下一個字母  
            Integer value = tm.get(ch[i]);  
            if (value != null)  
                count = value;  
            count++;  
            tm.put(ch[i],count);  
            count = 0;  
        }  
        //創(chuàng)建字符串容器,存入取出的鍵值即按順序排列的字符串  
        StringBuilder sb = new StringBuilder();  
        //迭代器取出相應(yīng)鍵值,并存入字符串容器  
        Iterator<Map.Entry<Character,Integer>> it = tm.entrySet().iterator();  
        while (it.hasNext())  
        {  
            Map.Entry<Character,Integer> me = it.next();  
            Character key = me.getKey();  
            Integer value = me.getValue();  
            sb.append(key + "(" + value + ")");  
        }  
        return sb.toString();  
    }  
}

6、集合映射的擴(kuò)展:

在很多項目中,應(yīng)用比較多的是一對多的映射關(guān)系,這就可以通過嵌套的形式將多個映射定義到一個大的集合中,并將大的集合分級處理,形成一個體系。
示例如下:

/* 
Map擴(kuò)展:一對多的映射關(guān)系 
如:學(xué)校中的  班級:學(xué)生:學(xué)號三者關(guān)系 
思路, 
    先創(chuàng)建大的集合,學(xué)校,如school 
    其中包含班級這個小集合,如room 
    班級中包含的學(xué)生有姓名,如name 
                學(xué)生有學(xué)號,如id 
*/  
import java.util.*;  
//創(chuàng)建學(xué)生類,定義私有屬性  
class Student  
{  
    private String name;  
    private String id;  
    Student(String name,String id)  
    {  
        this.name = name;  
        this.id = id;  
    }  
    //復(fù)寫toString方法,給出指定字符串形式  
    public String toString()  
    {  
        return name + ":" + id;  
    }  
}  
//測試  
class MapsDemo  
{  
    public static void main(String[] args)   
    {  
        //創(chuàng)建一個學(xué)校,里面有班級  
        HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>();  
        //創(chuàng)建兩個班級,里面有學(xué)生  
        //基礎(chǔ)班  
        HashMap<String,String> base = new HashMap<String,String>();  
        //預(yù)熱班  
        HashMap<String,String> adv = new HashMap<String,String>();  
        //將信息分別加入集合  
        //學(xué)校中的班級信息  
        czbk.put("Base",base);  
        czbk.put("Adv",adv);  
        //基礎(chǔ)班中的學(xué)生信息  
        base.put("01","BS01");  
        base.put("02","BS02");  
        base.put("03","BS03");  
        //提高班中的學(xué)生信息  
        adv.put("01","ADV01");   
        adv.put("02","ADV02");   
        adv.put("03","ADV03");  
        //調(diào)用取出信息的方法  
        String all = getAll(czbk);  
        System.out.println("ALL: \n" + all);  
    }  
  
    //定義取出方法  
    //定義取出學(xué)校中班級的方法,并調(diào)用取出學(xué)生信息方法  
    public static String getAll(HashMap<String,HashMap<String,String>> school)  
    {  
        //定義存儲班級信息字符串容器  
        StringBuilder sb = new StringBuilder();  
        //初始化班級為空  
        String room = null;  
        //將學(xué)校中的班級存入Set集合,并用迭代器獲取  
        Set<String> keySet = school.keySet();  
        Iterator<String> it = keySet.iterator();  
        while(it.hasNext())  
        {  
            room = it.next();  
            //取出班級中的學(xué)生信息也放在容器中  
            HashMap<String,String>  hm = school.get(room);  
            //將班級中的學(xué)生信息字符串形式存入字符串容器中  
            sb.append(room + ":\n"+ getRoom(hm) );  
        }  
        //返回一個容器字符串,為學(xué)生信息  
        return sb.toString();  
    }  
    //定義取出班級中學(xué)生信息的方法,被上面的方法調(diào)用  
    public static String getRoom(HashMap<String,String> room)  
    {  
        //定義存儲學(xué)生信息的字符串容器  
        StringBuilder sb = new StringBuilder();  
        //將班級中的學(xué)生信息存入Set集合,并用迭代器獲取  
        Set<Map.Entry<String,String>> entrySet = room.entrySet();  
        Iterator<Map.Entry<String,String>> it = entrySet.iterator();  
        while(it.hasNext())  
        {  
            //將映射關(guān)系存入Map.Entry的集合中,并獲取相應(yīng)鍵值  
            Map.Entry<String,String> me = it.next();  
            String key = me.getKey();  
            String value = me.getValue();  
            //將學(xué)生信息存入到字符串容器中  
            sb.append(key + "::" + value + "\n");  
        }  
        //放回存有學(xué)生信息的字符串容器  
        return sb.toString();   
    }  
}

集合間區(qū)別

一、List接口

List接口對Collection進(jìn)行了簡單的擴(kuò)充,它的具體實現(xiàn)類常用的有ArrayList和LinkedList。
你可以將任何東西放到一個List容器中,并在需要時從中取出。

ArrayList從其命名中可以看出它是一種類似數(shù)組的形式進(jìn)行存儲,因此它的隨機(jī)訪問速度極快,而LinkedList的內(nèi)部實現(xiàn)是鏈表,它適合于在鏈表中間需要頻繁進(jìn)行插入和刪除操作。在具體應(yīng)用時可以根據(jù)需要自由選擇。

前面說的Iterator只能對容器進(jìn)行向前遍歷,而ListIterator則繼承了Iterator的思想,并提供了對List進(jìn)行雙向遍歷的方法。

二、Set接口

Set接口也是Collection的一種擴(kuò)展。

而與List不同的是,在Set中的對象元素不能重復(fù),也就是說你不能把同樣的東西兩次放入同一個Set容器中。

它的常用具體實現(xiàn)有HashSet和TreeSet類。

HashSet能快速定位一個元素,但是你放到HashSet中的對象需要實現(xiàn)hashCode()方法,它使用了前面說過的哈希碼的算法。

而TreeSet則將放入其中的元素按序存放,這就要求你放入其中的對象是可排序的,這就用到了集合框架提供的另外兩個實用類Comparable和Comparator。

一個類是可排序的,它就應(yīng)該實現(xiàn)Comparable接口。有時多個類具有相同的排序算法,那就不需要在每分別重復(fù)定義相同的排序算法,只要實現(xiàn)Comparator接口即可。

集合框架中還有兩個很實用的公用類:Collections和Arrays。
Collections提供了對一個Collection容器進(jìn)行諸如排序、復(fù)制、查找和填充等一些非常有用的方法,Arrays則是對一個數(shù)組進(jìn)行類似的操作。

三、Map

Map是一種把鍵對象和值對象進(jìn)行關(guān)聯(lián)的容器,而一個值對象又可以是一個Map,依次類推,這樣就可形成一個多級映射。

對于鍵對象來說,像Set一樣,一個Map容器中的鍵對象不允許重復(fù),這是為了保持查找結(jié)果的一致性;如果有兩個鍵對象一樣,那你想得到那個鍵對象所對應(yīng)的值對象時就有問題了,可能你得到的并不是你想的那個值對象,結(jié)果會造成混亂,所以鍵的唯一性很重要,也是符合集合的性質(zhì)的。

當(dāng)然在使用過程中,某個鍵所對應(yīng)的值對象可能會發(fā)生變化,這時會按照最后一次修改的值對象與鍵對應(yīng)。對于值對象則沒有唯一性的要求。你可以將任意多個鍵都映射到一個值對象上,這不會發(fā)生任何問題(不過對你的使用卻可能會造成不便,你不知道你得到的到底是那一個鍵所對應(yīng)的值對象)。

Map有兩種比較常用的實現(xiàn):HashMap和TreeMap。
HashMap也用到了哈希碼的算法,以便快速查找一個鍵,
TreeMap則是對鍵按序存放,因此它便有一些擴(kuò)展的方法,比如firstKey(),lastKey()等,你還可以從TreeMap中指定一個范圍以取得其子Map。

鍵和值的關(guān)聯(lián)很簡單,用pub(Object key,Object value)方法即可將一個鍵與一個值對象相關(guān)聯(lián)。用get(Object key)可得到與此key對象所對應(yīng)的值對象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 概述 Java集合框架由Java類庫的一系列接口、抽象類以及具體實現(xiàn)類組成。我們這里所說的集合就是把一組對象組織到...
    absfree閱讀 1,267評論 0 10
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,721評論 18 399
  • Java集合框架 Java平臺提供了一個全新的集合框架。“集合框架”主要由一組用來操作對象的接口組成。不同接口描述...
    小石38閱讀 364評論 0 0
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 886評論 0 1
  • 八月十五,中秋月圓。 每月都有一次月圓的時候,全年共有十二次圓月。但,國人好似對八月十五——中秋的圓月,有著特別的...
    自由心空閱讀 783評論 4 5