2接口详解_java集合【2】——— Collection接口详解
一、Collection接口簡(jiǎn)介
二、Collection源碼分析
三、Collection的子類(lèi)以及子類(lèi)的實(shí)現(xiàn)
3.1 List extend Collection
3.2 Set extend Collection
3.3 Queue extend Collection
四、Collection和Map的辨析
五、Collection和Collections的辨析
六、總結(jié)
一、Collection接口簡(jiǎn)介
collection在java集合中,算是頂級(jí)接口,它繼承了iterable接口,不能實(shí)例化,只能實(shí)例化其子類(lèi)。之所以需要這樣一個(gè)接口,是因?yàn)閖ava作為面向?qū)ο?#xff0c;總是避免不了處理多個(gè)對(duì)象的情況,要處理多個(gè)對(duì)象,首先需要容器存儲(chǔ),這個(gè)容器就是集合。為什么有了數(shù)組,還需要集合,因?yàn)閿?shù)組的功能單一,長(zhǎng)度不可變,而有些集合實(shí)現(xiàn)類(lèi)則是對(duì)數(shù)組操作的封裝。
Collection集合和數(shù)組的區(qū)別:
- 集合長(zhǎng)度可以變,數(shù)組是定長(zhǎng)的
- 集合存儲(chǔ)的元素只能是引用類(lèi)型,而數(shù)組則可以是基本類(lèi)型
- 數(shù)組只能執(zhí)行基本操作,而集合功能經(jīng)過(guò)拓展,更加豐富。
Collection -->List-有順序,可重復(fù)
List-有順序,可重復(fù) -->LinkedList-使用鏈表實(shí)現(xiàn),線程不安全
List-有順序,可重復(fù) -->ArrayList-數(shù)組實(shí)現(xiàn),線程不安全
List-有順序,可重復(fù) -->Vector-數(shù)組實(shí)現(xiàn),線程安全
Vector-數(shù)組實(shí)現(xiàn),線程安全 -->Stack-堆棧,先進(jìn)后出
Collection-->Set-不可重復(fù),內(nèi)部排序
Set-不可重復(fù),內(nèi)部排序-->HashSet-hash表存儲(chǔ)
HashSet-hash表存儲(chǔ)-->LinkHashSet-鏈表維護(hù)插入順序
Set-不可重復(fù),內(nèi)部排序-->TreeSet-二叉樹(shù)實(shí)現(xiàn),排序
Collection-->Queue-隊(duì)列,先進(jìn)先出
二、Collection源碼分析
Collection繼承于Iterable接口,而Iterable接口,是集合的頂級(jí)接口,沒(méi)有之一,Iterable接口定義的功能是可以迭代,也就是獲取迭代器iterator的功能,因此Collection以及其實(shí)現(xiàn)類(lèi)也間接獲得迭代的功能。
為什么需要這樣子定義呢?我陷入了深深地思考...?
其實(shí),這也算是哲學(xué)問(wèn)題,java的類(lèi)的設(shè)計(jì)是經(jīng)過(guò)很長(zhǎng)時(shí)間的考驗(yàn)以及調(diào)整形成的,平衡修改以及耦合等各方面的原因,結(jié)構(gòu)更加清晰,維護(hù)成本更低,邏輯性更強(qiáng)。這些接口就是一個(gè)個(gè)標(biāo)準(zhǔn)或者規(guī)范,其子類(lèi)就是不斷拓展功能,這些接口的形成是一種抽象,將能迭代事物抽象成為迭代器iterator,將獲取迭代器,也就是迭代能力抽象成iterable。Collection則是獲得迭代能力的接口之一,其實(shí)Map的實(shí)現(xiàn)類(lèi)里面也是有使用到iterable接口,幾乎所有的集合實(shí)現(xiàn)類(lèi)都是需要遍歷元素的,所以這個(gè)iterable也是必須存在的,存在即合理。
下面看Collection接口以及iterable接口的方法對(duì)比:從上面的圖我們可以看出,iterable接口功能主要是
- 獲取迭代器iterator
- foreach()遍歷
- 獲取可切分迭代器Spliterator
Collection接口在此基礎(chǔ)上進(jìn)行拓展,源碼接口如下:
boolean?add(Object?o)????//添加元素boolean?remove(Object?o)??//移除元素boolean?addAll(Collection?c)?//批量添加boolean?removeAll(Collection?c)??//批量移除void?retainAll(Collection?c)???//?移除在c中不存在的元素void?clear()??//清空集合int?size()???//集合大小boolean?isEmpty()????//是否為空boolean?contains(Object?o)????//是否包含在集合中boolean?containsAll(Collection?c)????//是否包含所有的元素Iterator?iterator()????//?獲取迭代器
Object[]?toArray()???//?轉(zhuǎn)成數(shù)組default?boolean?removeIf(Predicate?super?E>?filter)?{}?//?刪除集合中復(fù)合條件的元素,刪除成功返回true
boolean?equals(Object?o)int?hashCode()default?Spliterator?spliterator()?{}?//獲取可分割迭代器
default?Stream?stream()?{}???//獲取流
default?Stream?parallelStream()?{}?//獲取并行流
里面獲取并行流的方法parallelStream(),其實(shí)就是通過(guò)默認(rèn)的ForkJoinPool(主要用來(lái)使用分治法(Divide-and-Conquer Algorithm)來(lái)解決問(wèn)題),提高多線程任務(wù)的速度。我們可以使用ArrayList來(lái)演示一下平行處理能力。例如下面的例子,輸出的順序就不一定是1,2,3...,可能是亂序的,這是因?yàn)槿蝿?wù)會(huì)被分成多個(gè)小任務(wù),任務(wù)執(zhí)行是沒(méi)有特定的順序的。
List?list?=?Arrays.asList(1,?2,?3,?4,?5,?6,?7,?8,?9);list.parallelStream()
???????.forEach(out::println);
上面源代碼可以看出,Collection接口定義了功能規(guī)范,有以下功能方法:
- 添加元素
- 刪除元素
- 判斷是否包含/是否全部包含/是否為空
- 獲取迭代器/可分割迭代器
- 獲取長(zhǎng)度
- 取交集
- 獲取流/并行流
我們遍歷元素的時(shí)候可以獲取Iterator,但是具體的實(shí)現(xiàn)是以子類(lèi)的特性去實(shí)現(xiàn)的,比如ArrayList是用內(nèi)部類(lèi)的方式實(shí)現(xiàn)了Iterator接口。
三、Collection的子類(lèi)以及子類(lèi)的實(shí)現(xiàn)
繼承Collection的子類(lèi)關(guān)系如下:
上面的類(lèi)圖已經(jīng)足夠清楚,下面是一些簡(jiǎn)單的概括(上面的類(lèi)型是使用IDEA的類(lèi)圖功能自動(dòng)生成,簡(jiǎn)直不能太好用???感覺(jué)發(fā)現(xiàn)了新大陸)
3.1 List extend Collection
繼承于Collection接口,有順序,取出的順序與存入的順序一致,有索引,可以根據(jù)索引獲取數(shù)據(jù),允許存儲(chǔ)重復(fù)的元素,可以放入為null的元素。
最常見(jiàn)的三個(gè)實(shí)現(xiàn)類(lèi)就是ArrayList,Vector,LinkedList,ArrayList和Vector都是內(nèi)部封裝了對(duì)數(shù)組的操作,唯一不同的是,Vector是線程安全的,而ArrayList不是,理論上ArrayList操作的效率會(huì)比Vector好一些。
里面是接口定義的方法:
int?size();??//獲取大小boolean?isEmpty();??//判斷是否為空
boolean?contains(Object?o);??//是否包含某個(gè)元素
Iterator?iterator();?//獲取迭代器
Object[]?toArray();??//?轉(zhuǎn)化成為數(shù)組(對(duì)象)
?T[]?toArray(T[]?a);??//?轉(zhuǎn)化為數(shù)組(特定位某個(gè)類(lèi))boolean?add(E?e);?//添加boolean?remove(Object?o);??//移除元素boolean?containsAll(Collection>?c);?//?是否包含所有的元素boolean?addAll(Collection?extends?E>?c);?//批量添加boolean?addAll(int?index,?Collection?extends?E>?c);?//批量添加,指定開(kāi)始的索引boolean?removeAll(Collection>?c);?//批量移除boolean?retainAll(Collection>?c);?//將c中不包含的元素移除default?void?replaceAll(UnaryOperator?operator)?{}//替換default?void?sort(Comparator?super?E>?c)?{}//?排序void?clear();//清除所有的元素boolean?equals(Object?o);//是否相等int?hashCode();?//計(jì)算獲取hash值E?get(int?index);?//通過(guò)索引獲取元素E?set(int?index,?E?element);//修改元素void?add(int?index,?E?element);//在指定位置插入元素E?remove(int?index);//根據(jù)索引移除某個(gè)元素int?indexOf(Object?o);??//根據(jù)對(duì)象獲取索引int?lastIndexOf(Object?o);?//獲取對(duì)象元素的最后一個(gè)元素ListIterator?listIterator();?//?獲取List迭代器ListIterator?listIterator(int?index);?//?根據(jù)索引獲取當(dāng)前的位置的迭代器List?subList(int?fromIndex,?int?toIndex);?//截取某一段數(shù)據(jù)default?Spliterator?spliterator(){}?//獲取可切分迭代器
上面的方法都比較簡(jiǎn)單,值得一提的是里面出現(xiàn)了ListIterator,這是一個(gè)功能更加強(qiáng)大的迭代器,繼承于Iterator,只能用于List類(lèi)型的訪問(wèn),拓展功能例如:通過(guò)調(diào)用listIterator()方法獲得一個(gè)指向List開(kāi)頭的ListIterator,也可以調(diào)用listIterator(n)獲取一個(gè)指定索引為n的元素的ListIterator,這是一個(gè)可以雙向移動(dòng)的迭代器。
操作數(shù)組索引的時(shí)候需要注意,由于List的實(shí)現(xiàn)類(lèi)底層很多都是數(shù)組,所以索引越界會(huì)報(bào)錯(cuò)IndexOutOfBoundsException。
說(shuō)起List的實(shí)現(xiàn)子類(lèi):
- ArrayList:底層存儲(chǔ)結(jié)構(gòu)是數(shù)組結(jié)構(gòu),增加刪除比較慢,查找比較快,是最常用的List集合。線程不安全。
- LinkedList:底層是鏈表結(jié)構(gòu),增加刪除比較快,但是查找比較慢。線程不安全。
- Vector:和ArrayList差不多,但是是線程安全的,即同步。
3.2 Set extend Collection
Set接口,不允許放入重復(fù)的元素,也就是如果相同,則只存儲(chǔ)其中一個(gè)。
下面是源碼方法:
int?size();?//獲取大小boolean?isEmpty();??//是否為空
?
boolean?contains(Object?o);?//是否包含某個(gè)元素
Iterator?iterator();?//獲取迭代器
Object[]?toArray();?//轉(zhuǎn)化成為數(shù)組
?T[]?toArray(T[]?a);?//轉(zhuǎn)化為特定類(lèi)的數(shù)組boolean?add(E?e);???//添加元素boolean?remove(Object?o);???//移除元素boolean?containsAll(Collection>?c);???//是否包含所有的元素boolean?addAll(Collection?extends?E>?c);??//批量添加boolean?retainAll(Collection>?c);?//移除所有不存在于c集合中的元素boolean?removeAll(Collection>?c);?//移除所有在c集合中存在的元素void?clear();???//清空集合boolean?equals(Object?o);???//是否相等int?hashCode();?//計(jì)算hashcodedefault?Spliterator?spliterator()?{}?????//獲取可分割迭代器
主要的子類(lèi):
- HashSet
- 允許空值
- 通過(guò)HashCode方法計(jì)算獲取hash值,確定存儲(chǔ)位置,無(wú)序。
- 底層是哈希表,一個(gè)元素為鏈表的數(shù)組
- LinkedHashSet
- HashSet的子類(lèi)
- 有順序
- 底層由哈希表組成
- TreeSet
- 如果無(wú)參數(shù)構(gòu)建Set,則需要實(shí)現(xiàn)Comparable方法。
- 亦可以創(chuàng)建時(shí)傳入比較方法,用于排序。
3.3 Queue extend Collection
隊(duì)列接口,在Collection接口的接觸上添加了增刪改查接口定義,一般默認(rèn)是先進(jìn)先出,即FIFO,除了優(yōu)先隊(duì)列和棧,優(yōu)先隊(duì)列是自己定義了排序的優(yōu)先順序,隊(duì)列中不允許放入null元素。
下面是源碼:
boolean?add(E?e);???//插入一個(gè)元素到隊(duì)列,失敗時(shí)返回IllegalStateException?(如果隊(duì)列容量不夠)boolean?offer(E?e);?//插入一個(gè)元素到隊(duì)列,失敗時(shí)返回false
E?remove();?//移除隊(duì)列頭的元素并移除
E?poll();???//返回并移除隊(duì)列的頭部元素,隊(duì)列為空時(shí)返回null
E?element();????//返回隊(duì)列頭元素
E?peek();???//返回隊(duì)列頭部的元素,隊(duì)列為空時(shí)返回null
主要的子接口以及實(shí)現(xiàn)類(lèi)有:
- Deque(接口):Queue的子接口,雙向隊(duì)列,可以從兩邊存取
- ArrayDeque:Deque的實(shí)現(xiàn)類(lèi),底層用數(shù)組實(shí)現(xiàn),數(shù)據(jù)存貯在數(shù)組中
- AbstractQueue:Queue的子接口,僅實(shí)現(xiàn)了add、remove和element三個(gè)方法
- PriorityQueue:按照默認(rèn)或者自己定義的順序來(lái)排序元素,底層使用堆(完全二叉樹(shù))實(shí)現(xiàn),使用動(dòng)態(tài)數(shù)組實(shí)現(xiàn),
- BlockingQueue:在java.util.concurrent包中,阻塞隊(duì)列,滿足當(dāng)前無(wú)法處理的操作。
對(duì)于Collection集合我們應(yīng)該使用哪一個(gè)?
每個(gè)實(shí)現(xiàn)都有自己的特點(diǎn),重要的是知道當(dāng)前數(shù)據(jù)以及業(yè)務(wù)的特點(diǎn),選取最適合的集合類(lèi)進(jìn)行數(shù)據(jù)操作。
- 元素唯一(Set)
- 唯一,有序 (自定義排序):TreeSet(速度較慢)
- FIFO,按照插入順序,唯一:LinkedHashSet(速度較快)
- 需要排序
- 不需要排序:HashSet(速度最快)
- 元素唯一
- 普通排隊(duì) :Queue的子類(lèi)
- 兩端都可以排隊(duì):ArrayDeque
- 按照自己定義的規(guī)則排序:PriorityQueue
- 處理排隊(duì)當(dāng)前無(wú)法處理太多請(qǐng)求(相當(dāng)于緩沖):阻塞隊(duì)列接口BlockingQueue
- 線程安全:Vector
- 接受線程不安全
- 查詢比較多:ArrayList
- 增加刪除操作較多:LinkedList
- 列表:List
- 排隊(duì)
四、Collection和Map的辨析
- Collection接口是存儲(chǔ)單列元素,而Map是鍵值對(duì),也就是存儲(chǔ)了雙列元素。
- Collection接口繼承了Iterable接口,而Map則不是,Map是在各自的實(shí)現(xiàn)類(lèi)中才用內(nèi)部類(lèi)的方式實(shí)現(xiàn)Iterator接口,例如HashMap,key或者value或者它們的組合entry都可以使用迭代器進(jìn)行遍歷。
- 兩個(gè)的子類(lèi)其實(shí)是有交集的,比如HashSet的底層實(shí)現(xiàn)其實(shí)就是定義了一個(gè)HashMap,TreeSet同樣依賴于Map接口的子實(shí)現(xiàn)類(lèi)TreeMap。
Map集合可以存儲(chǔ)鍵值對(duì),可以獲取所有的鍵,或者值或者鍵值對(duì),鍵不允許重復(fù),但是值可以重復(fù)。隨便說(shuō)說(shuō)Map相關(guān)的子類(lèi):
- HashTable:
- 源于JDK1.1,底層使用數(shù)組和鏈表
- 線程安全,不允許null作為key或者value
- HashMap:
- 源于JDK1.2,JDK1.7以及之前使用數(shù)組+鏈表實(shí)現(xiàn),JDK1.8使用數(shù)組+鏈表/紅黑樹(shù)
- 線程不安全
- LinkedHashMap:
- 保存了插入的順序,可以按照順序遍歷
- TreeMap:
- 實(shí)現(xiàn)了SortMap接口,可以把保存的記錄按照鍵排序
- 底層是用紅黑樹(shù)實(shí)現(xiàn)
五、Collection和Collections的辨析
(1).Collection是集合的頂級(jí)接口之一,衍生出了Set,List,Queue等一系列接口以及實(shí)現(xiàn)類(lèi)。而Collections是一個(gè)輔助類(lèi),就是實(shí)現(xiàn)一些排序,搜索,線程安全等功能,它主要體現(xiàn)的功能是操作集合,而Collection則是集合本身。
(2).Collection是接口,其本身不能實(shí)例化,但是可以實(shí)例化為其子類(lèi)或者實(shí)現(xiàn)類(lèi),但是Collections是包裝類(lèi),一般不會(huì)實(shí)例化,直接調(diào)用static方法。
Collections接口主要提供了以下操作,只展示了部分,詳細(xì)需要后面文章說(shuō):
六、總結(jié)
Collection接口繼承了iterable接口,是集合的頂級(jí)接口之一,衍生接口有List,Set,Queue等,主要定義了元素的基本操作,刪除,添加等等方法,迭代一個(gè)Collection可以使用Iterator,但是Collection本身不能實(shí)例化。
- END -總結(jié)
以上是生活随笔為你收集整理的2接口详解_java集合【2】——— Collection接口详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 小批量随机梯度下降
- 下一篇: 干货|MIT线性代数课程精细笔记5