由淺入深理解java集合(一)——集合框架 Collection、Map

本篇文章主要對(duì)java集合的框架進(jìn)行介紹,使大家對(duì)java集合的整體框架有個(gè)了解。具體介紹了Collection接口,Map接口以及Collection接口的三個(gè)子接口Set,List,Queue。

Java集合類(lèi)簡(jiǎn)介:

Java集合大致可以分為Set、List、Queue和Map四種體系,其中Set代表無(wú)序、不可重復(fù)的集合;List代表有序、重復(fù)的集合;而Map則代表具有映射關(guān)系的集合,Java 5 又增加了Queue體系集合,代表一種隊(duì)列集合實(shí)現(xiàn)。
Java集合就像一種容器,可以把多個(gè)對(duì)象(實(shí)際上是對(duì)象的引用,但習(xí)慣上都稱(chēng)對(duì)象)“丟進(jìn)”該容器中。從Java 5 增加了泛型以后,Java集合可以記住容器中對(duì)象的數(shù)據(jù)類(lèi)型,使得編碼更加簡(jiǎn)潔、健壯。

Java集合和數(shù)組的區(qū)別:

1.數(shù)組長(zhǎng)度在初始化時(shí)指定,意味著只能保存定長(zhǎng)的數(shù)據(jù)。而集合可以保存數(shù)量不確定的數(shù)據(jù)。同時(shí)可以保存具有映射關(guān)系的數(shù)據(jù)(即關(guān)聯(lián)數(shù)組,鍵值對(duì) key-value)。
2.數(shù)組元素即可以是基本類(lèi)型的值,也可以是對(duì)象。集合里只能保存對(duì)象(實(shí)際上只是保存對(duì)象的引用變量),基本數(shù)據(jù)類(lèi)型的變量要轉(zhuǎn)換成對(duì)應(yīng)的包裝類(lèi)才能放入集合類(lèi)中。

Java集合類(lèi)之間的繼承關(guān)系:

Java的集合類(lèi)主要由兩個(gè)接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口。



圖中,ArrayList,HashSet,LinkedList,TreeSet是我們經(jīng)常會(huì)有用到的已實(shí)現(xiàn)的集合類(lèi)。

Map實(shí)現(xiàn)類(lèi)用于保存具有映射關(guān)系的數(shù)據(jù)。Map保存的每項(xiàng)數(shù)據(jù)都是key-value對(duì),也就是由key和value兩個(gè)值組成。Map里的key是不可重復(fù)的,key用戶(hù)標(biāo)識(shí)集合里的每項(xiàng)數(shù)據(jù)。


圖中,HashMap,TreeMap是我們經(jīng)常會(huì)用到的集合類(lèi)。

Collection接口:

簡(jiǎn)介

Collection接口是Set,Queue,List的父接口。Collection接口中定義了多種方法可供其子類(lèi)進(jìn)行實(shí)現(xiàn),以實(shí)現(xiàn)數(shù)據(jù)操作。由于方法比較多,就偷個(gè)懶,直接把JDK文檔上的內(nèi)容搬過(guò)來(lái)。

接口中定義的方法


可以看出Collection用法有:添加元素,刪除元素,返回Collection集合的個(gè)數(shù)以及清空集合等。
其中重點(diǎn)介紹iterator()方法,該方法的返回值是Iterator<E>。

使用Iterator遍歷集合元素

Iterator接口經(jīng)常被稱(chēng)作迭代器,它是Collection接口的父接口。但I(xiàn)terator主要用于遍歷集合中的元素。
Iterator接口中主要定義了2個(gè)方法:



下面程序簡(jiǎn)單示范了通過(guò)Iterator對(duì)象逐個(gè)獲取元素的邏輯。

public class IteratorExample {
    public static void main(String[] args){
        //創(chuàng)建集合,添加元素  
        Collection<Day> days = new ArrayList<Day>();
        for(int i =0;i<10;i++){
            Day day = new Day(i,i*60,i*3600);
            days.add(day);
        }
        //獲取days集合的迭代器
        Iterator<Day> iterator = days.iterator();
        while(iterator.hasNext()){//判斷是否有下一個(gè)元素
            Day next = iterator.next();//取出該元素
            //逐個(gè)遍歷,取得元素后進(jìn)行后續(xù)操作
            .....
        }
    }

}

注意:當(dāng)使用Iterator對(duì)集合元素進(jìn)行迭代時(shí),Iterator并不是把集合元素本身傳給了迭代變量,而是把集合元素的值傳給了迭代變量(就如同參數(shù)傳遞是值傳遞,基本數(shù)據(jù)類(lèi)型傳遞的是值,引用類(lèi)型傳遞的僅僅是對(duì)象的引用變量),所以修改迭代變量的值對(duì)集合元素本身沒(méi)有任何影響。
下面的程序演示了這一點(diǎn):

public class IteratorExample {
    public static void main(String[] args){
        List<String> list =Arrays.asList("java語(yǔ)言","C語(yǔ)言","C++語(yǔ)言");
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String next = iterator.next();//集合元素的值傳給了迭代變量,僅僅傳遞了對(duì)象引用。保存的僅僅是指向?qū)ο髢?nèi)存空間的地址
            next ="修改后的";
            System.out.println(next);
            
        }
        System.out.println(list);
    }

}

輸出結(jié)果如下:

修改后的
修改后的
修改后的
[java語(yǔ)言, C語(yǔ)言, C++語(yǔ)言]

下面具體介紹Collection接口的三個(gè)子接口Set,List,Queue。

Set集合

簡(jiǎn)介

Set集合與Collection集合基本相同,沒(méi)有提供任何額外的方法。實(shí)際上Set就是Collection,只是行為略有不同(Set不允許包含重復(fù)元素)。
Set集合不允許包含相同的元素,如果試圖把兩個(gè)相同的元素加入同一個(gè)Set集合中,則添加操作失敗,add()方法返回false,且新元素不會(huì)被加入。

List集合

簡(jiǎn)介

List集合代表一個(gè)元素有序、可重復(fù)的集合,集合中每個(gè)元素都有其對(duì)應(yīng)的順序索引。List集合允許使用重復(fù)元素,可以通過(guò)索引來(lái)訪(fǎng)問(wèn)指定位置的集合元素 。List集合默認(rèn)按元素的添加順序設(shè)置元素的索引,例如第一個(gè)添加的元素索引為0,第二個(gè)添加的元素索引為1......
List作為Collection接口的子接口,可以使用Collection接口里的全部方法。而且由于List是有序集合,因此List集合里增加了一些根據(jù)索引來(lái)操作集合元素的方法。

接口中定義的方法

void add(int index, Object element): 在列表的指定位置插入指定元素(可選操作)。
**boolean addAll(int index, Collection<? extends E> c) : ** 將集合c 中的所有元素都插入到列表中的指定位置index處。
Object get(index):返回列表中指定位置的元素。
int indexOf(Object o): 返回此列表中第一次出現(xiàn)的指定元素的索引;如果此列表不包含該元素,則返回 -1。
int lastIndexOf(Object o):返回此列表中最后出現(xiàn)的指定元素的索引;如果列表不包含此元素,則返回 -1。
**Object remove(int index): ** 移除列表中指定位置的元素。
Object set(int index, Object element):用指定元素替換列表中指定位置的元素。
**List subList(int fromIndex, int toIndex): **返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之間的所有集合元素組成的子集。
Object[] toArray(): 返回按適當(dāng)順序包含列表中的所有元素的數(shù)組(從第一個(gè)元素到最后一個(gè)元素)。

除此之外,Java 8還為L(zhǎng)ist接口添加了如下兩個(gè)默認(rèn)方法。

void replaceAll(UnaryOperator operator):根據(jù)operator指定的計(jì)算規(guī)則重新設(shè)置List集合的所有元素。
void sort(Comparator c):根據(jù)Comparator參數(shù)對(duì)List集合的元素排序。

Queue集合

簡(jiǎn)介

Queue用戶(hù)模擬隊(duì)列這種數(shù)據(jù)結(jié)構(gòu),隊(duì)列通常是指“先進(jìn)先出”(FIFO,first-in-first-out)的容器。隊(duì)列的頭部是在隊(duì)列中存放時(shí)間最長(zhǎng)的元素,隊(duì)列的尾部是保存在隊(duì)列中存放時(shí)間最短的元素。新元素插入(offer)到隊(duì)列的尾部,訪(fǎng)問(wèn)元素(poll)操作會(huì)返回隊(duì)列頭部的元素。通常,隊(duì)列不允許隨機(jī)訪(fǎng)問(wèn)隊(duì)列中的元素。

接口中定義的方法

Map集合

簡(jiǎn)介

Map用戶(hù)保存具有映射關(guān)系的數(shù)據(jù),因此Map集合里保存著兩組數(shù),一組值用戶(hù)保存Map里的key,另一組值用戶(hù)保存Map里的value,key和value都可以是任何引用類(lèi)型的數(shù)據(jù)。Map的key不允許重復(fù),即同一個(gè)Map對(duì)象的任何兩個(gè)key通過(guò)equals方法比較總是返回false。
如下圖所描述,key和value之間存在單向一對(duì)一關(guān)系,即通過(guò)指定的key,總能找到唯一的、確定的value。從Map中取出數(shù)據(jù)時(shí),只要給出指定的key,就可以取出對(duì)應(yīng)的value。


Map集合與Set集合、List集合的關(guān)系

1.與Set集合的關(guān)系
如果 把Map里的所有key放在一起看,它們就組成了一個(gè)Set集合(所有的key沒(méi)有順序,key與key之間不能重復(fù)),實(shí)際上Map確實(shí)包含了一個(gè)keySet()方法,用戶(hù)返回Map里所有key組成的Set集合。
2.與List集合的關(guān)系
如果把Map里的所有value放在一起來(lái)看,它們又非常類(lèi)似于一個(gè)List:元素與元素之間可以重復(fù),每個(gè)元素可以根據(jù)索引來(lái)查找,只是Map中索引不再使用整數(shù)值,而是以另外一個(gè)對(duì)象作為索引。

接口中定義的方法


Map中還包括一個(gè)內(nèi)部類(lèi)Entry,該類(lèi)封裝了一個(gè)key-value對(duì)。Entry包含如下三個(gè)方法:



Map集合最典型的用法就是成對(duì)地添加、刪除key-value對(duì),然后就是判斷該Map中是否包含指定key,是否包含指定value,也可以通過(guò)Map提供的keySet()方法獲取所有key組成的集合,然后使用foreach循環(huán)來(lái)遍歷Map的所有key,根據(jù)key即可遍歷所有的value。下面程序代碼示范Map的一些基本功能:

public class MapTest {
    public static void main(String[] args){
        Day day1 = new Day(1, 2, 3);
        Day day2 = new Day(2, 3, 4);
        Map<String,Day> map = new HashMap<String,Day>();
        //成對(duì)放入key-value對(duì)
        map.put("第一個(gè)", day1);
        map.put("第二個(gè)", day2);
        //判斷是否包含指定的key
        System.out.println(map.containsKey("第一個(gè)"));
        //判斷是否包含指定的value
        System.out.println(map.containsValue(day1));
        //循環(huán)遍歷
        //1.獲得Map中所有key組成的set集合
        Set<String> keySet = map.keySet();
        //2.使用foreach進(jìn)行遍歷
        for (String key : keySet) {
            //根據(jù)key獲得指定的value
            System.out.println(map.get(key));
        }
        //根據(jù)key來(lái)移除key-value對(duì)
        map.remove("第一個(gè)");
        System.out.println(map);
    }

}

輸出結(jié)果:

true
true
Day [hour=2, minute=3, second=4]
Day [hour=1, minute=2, second=3]
{第二個(gè)=Day [hour=2, minute=3, second=4]}

以上就java集合框架的概括內(nèi)容,通過(guò)這篇文章可以了解java集合中錯(cuò)中復(fù)雜的關(guān)系,同時(shí)掌握一些基本的概念以及對(duì)集合的操作方法。
后續(xù)文章將對(duì)java集合中的具體實(shí)現(xiàn)類(lèi)進(jìn)行深入了解。有興趣的話(huà)可以觀看后續(xù)內(nèi)容,進(jìn)一步了解java集合內(nèi)容。

由淺入深理解java集合(二)——集合 Set
由淺入深理解java集合(三)——集合 List
由淺入深理解java集合(四)——集合 Queue
由淺入深理解java集合(五)——集合 Map
由淺入深理解java集合(六)——集合增刪改查的細(xì)節(jié)、性能及選擇推薦(待更新)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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