文章首發(fā)博客地址:https://blog.csdn.net/u013277209?viewmode=contents
前言
本篇文章作為吃透Java集合系列第二篇文章椎组,主要探討Collection接口及其子接口List乎串、Set、Queue旺上。通過本篇文章我們需要明白如下幾個問題:
1、Collection的作用糖埋?
2宣吱、List、Set瞳别、Queue接口對Collection接口做了哪些擴(kuò)展征候,各自有什么特點(diǎn)杭攻?
一:Collection接口
Collection接口是集合層次的根接口,定義了集合的通用操作疤坝,所有集合都是在Collection基礎(chǔ)上進(jìn)行擴(kuò)展的兆解。
先看一下Collection的源碼:
/**
* 集合層次結(jié)構(gòu)中的根接口。一個集合代表一組對象卒煞,被稱為元素痪宰。
* 一些集合允許重復(fù)的元素,而有些則不允許畔裕。一些是有序的衣撬,另一些是無序的。
* JDK沒有提供這個接口的任何直接的實(shí)現(xiàn):它提供更具體的子接口像 Set和 List實(shí)現(xiàn)扮饶。
*
* 所有通用的Collection實(shí)現(xiàn)類(通常通過其子接口間接實(shí)現(xiàn)Collection)應(yīng)該提供兩個“標(biāo)準(zhǔn)”構(gòu)造函數(shù):
* void(無參數(shù)) 構(gòu)造函數(shù)具练,它創(chuàng)建一個空集合,以及一個帶有Collection類型的單個參數(shù)的構(gòu)造函數(shù)甜无,
* 它創(chuàng)建一個與它的參數(shù)具有相同元素的新集合扛点。實(shí)際上,后者的構(gòu)造函數(shù)允許用戶復(fù)制任何集合岂丘,生成所需實(shí)現(xiàn)類型的等效集合陵究。
* 沒有辦法強(qiáng)制執(zhí)行這個約定(因?yàn)榻涌诓荒馨瑯?gòu)造函數(shù)),但是Java平臺庫中的所有通用Collection實(shí)現(xiàn)都符合奥帘。
*
* 如果這個集合不支持某個操作的話铜邮,調(diào)用這些方法可能(但不是必需)拋出 UnsupportedOperationException
*/
public interface Collection<E> extends Iterable<E> {
/**
* 此方法成功完成后,可確保對象包含在集合中寨蹋。
* 如果集合被修改松蒜,則返回true,如果沒有更改已旧,則返回false秸苗。
*/
boolean add(E e)
/**
* 將指定集合中的所有元素添加到這個集合
*/
boolean addAll(Collection<? extends E> c)
/**
* 從這個集合中移除指定元素的一個實(shí)例
*/
boolean remove(Object o)
/**
* 刪除此集合中包含的所有元素的所有元素。
*/
boolean removeAll(Collection<?> c)
/**
* 刪除滿足給定謂詞的這個集合的所有元素运褪。
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
/**
* 從這個集合中移除所有不包含在指定集合中的元素的所有元素惊楼。
*/
boolean retainAll(Collection<?> c)
/**
* 從這個集合中移除所有的元素
*/
void clear()
/**
* 返回此集合中的元素的數(shù)目。如果這個集合包含多 Integer.MAX_VALUE元素,返回 Integer.MAX_VALUE。
*/
int size();
/**
* 如果此Collection不包含元素衅枫,則返回true
*/
boolean isEmpty()
/**
* 如果集合包含指定元素,返回 true攀芯。
*/
boolean contains(Object o)
/**
* 返回 true如果這個集合包含指定集合的所有元素。
*/
boolean containsAll(Collection<?> c)
/**
* 返回一個包含此集合中包含的所有元素的新數(shù)組文虏。
* 如果實(shí)現(xiàn)已經(jīng)排序了元素侣诺,它將以與迭代器返回的順序相同的順序返回元素?cái)?shù)組殖演。
* 返回的數(shù)組不反映集合的任何更改。 即使底層數(shù)據(jù)結(jié)構(gòu)已經(jīng)是一個數(shù)組年鸳,也創(chuàng)建一個新數(shù)組趴久。
*/
Object[] toArray()
/**
* 返回包含此集合中包含的所有元素的數(shù)組。 如果指定的數(shù)組足夠大以容納元素搔确,則使用指定的數(shù)組
* 否則將創(chuàng)建相同類型的數(shù)組彼棍。 如果使用指定的數(shù)組并且大于此集合,則Collection元素之后的數(shù)組元素將設(shè)置為null膳算。
*/
<T> T[] toArray(T[] a)
/**
* 重寫Object中的equals方法
*/
boolean equals(Object o)
/**
* 重寫Object中的hashCode方法
*/
int hashCode()
/**
* 返回可用于訪問此Collection所包含的對象的Iterator實(shí)例座硕。 沒有定義迭代器返回元素的順序。
* 只有當(dāng)Collection的實(shí)例具有定義的順序時涕蜂,才能按照該順序返回元素华匾。
*/
Iterator<E> iterator()
/**
* 返回一個并行迭代器類Spliterator
*/
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
/**
* 這個集合中的元素的順序 Stream
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* 返回一個可能并行 Stream與集合的來源。
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
- Collection接口是Java語言中最基本的集合接口机隙,在JDK中沒有直接提供Collection接口的具體實(shí)現(xiàn)類蜘拉,Collection的功能實(shí)現(xiàn)類主要是對它的三個更具體的子接口List、Set和Queue的具體實(shí)現(xiàn)類有鹿。但是在Collection接口中定義了一套通用操作的實(shí)現(xiàn)方法和命名規(guī)則旭旭。
- List、Set葱跋、Queue接口都繼承自Collection并定義了各自不同的方法對其擴(kuò)展持寄。
二:List接口
List接口擴(kuò)展了Collection,可以根據(jù)下標(biāo)index對元素進(jìn)行操作年局,每個元素都有唯一一個下標(biāo)對應(yīng)。
添加了功能更強(qiáng)大的ListIterator迭代器咸产,可以沿任一方向遍歷List矢否,并且在遍歷期間還可以修改List
/**
* List是維護(hù)其元素的排序的集合。 List中的每個元素都有一個索引脑溢。 因此僵朗,每個元素可以被其索引訪問,第一個索引為零屑彻。
* 通常验庙,與集合相比,List允許重復(fù)元素社牲,其中元素必須是唯一的粪薛。
* 有序集合(也稱為<i>序列</ i>)。 該接口的用戶可以精確控制每個元素插入到列表中的哪個位置搏恤。
* 用戶可以通過整數(shù)索引(列表中的位置)訪問元素违寿,并搜索列表中的元素湃交。
*
* 列表允許重復(fù)元素,也允許null元素插入
*/
public interface List<E> extends Collection<E> {
/**
* List作為Collection的子接口提供了Collection接口定義的方法
* 這些方法在Collection源碼中已經(jīng)分析過了藤巢,就不在說明了
*/
//增
boolean add(E e);
boolean addAll(Collection<? extends E> c);
//刪
boolean remove(Object o);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
default boolean removeIf(Predicate<? super E> filter)
void clear();
//查
int size();
boolean isEmpty();
boolean contains(Object o);
boolean containsAll(Collection<?> c);
//轉(zhuǎn)數(shù)組
Object[] toArray();
<T> T[] toArray(T[] a);
//重寫Object方法
boolean equals(Object o);
int hashCode();
//迭代器
Iterator<E> iterator();
default Spliterator<E> spliterator()
//同時List接口定義了一些自己的方法來實(shí)現(xiàn)“有序”這一功能特點(diǎn)
/**
*返回列表中指定索引的元素
*/
E get(int index);
/**
*設(shè)定某個列表索引的值
*/
E set(int index, E element);
/**
*在指定位置插入元素搞莺,當(dāng)前元素和后續(xù)元素后移
*這是可選操作,類似于順序表的插入操作
*/
void add(int index, E element);
/**
* 在指定位置插入指定集合中的元素掂咒,當(dāng)前元素和后續(xù)元素后移
*/
boolean addAll(int index, Collection<? extends E> c);
/**
* 刪除指定位置的元素(可選操作)
*/
E remove(int index);
/**
* 獲得指定對象的最小索引位置才沧,沒有則返回-1
*/
int indexOf(Object o);
/**
* 獲得指定對象的最大索引位置,可以知道的是若集合中無給定元素的重復(fù)元素下
* 其和indexOf返回值是一樣的
*/
int lastIndexOf(Object o);
/**
* 一種更加強(qiáng)大的迭代器绍刮,支持向前遍歷温圆,向后遍歷
* 插入刪除操作,此處不解釋
*/
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
/**
* 返回索引fromIndex(包括)和toIndex(不包括)之間的視圖录淡。
*/
List<E> subList(int fromIndex, int toIndex);
}
List集合特點(diǎn)
- 內(nèi)部元素是有序的 捌木,集合中每個元素都有其對應(yīng)的順序索引。
- 元素是可以重復(fù)的 嫉戚,因?yàn)樗梢酝ㄟ^索引來訪問指定位置的集合元素刨裆。
- List接口有3個常用的實(shí)現(xiàn)類,分別是ArrayList彬檀、LinkedList帆啃、Vector。
三:Set接口
Set接口完全繼承了Collection窍帝,在Collection基礎(chǔ)上并沒有什么改動努潘,但是增加了一個約定:不包含重復(fù)元素的集合!
接下來我們看一下源碼:
/**
* Set是不允許重復(fù)元素的數(shù)據(jù)結(jié)構(gòu)坤学。
*/
public interface Set<E> extends Collection<E> {
/**
* Set作為Collection的子接口提供了Collection接口定義的方法
* 這些方法在Collection源碼學(xué)習(xí)中已經(jīng)分析過了疯坤,就不在說明了
*/
//增
boolean add(E e);
boolean addAll(Collection<? extends E> c);
//刪
boolean remove(Object o);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
default boolean removeIf(Predicate<? super E> filter)
void clear();
//查
int size();
boolean isEmpty();
boolean contains(Object o);
boolean containsAll(Collection<?> c);
//轉(zhuǎn)數(shù)組
Object[] toArray();
<T> T[] toArray(T[] a);
//重寫Object方法
boolean equals(Object o);
int hashCode();
//迭代器
Iterator<E> iterator();
default Spliterator<E> spliterator()
}
Set內(nèi)部元素是無序的,元素是不可以重復(fù)的
四:Queue接口
1深浮、Queue是在處理之前保存元素的集合压怠。除了基本的Collection操作外,Queue還提供額外的插入飞苇、刪除和檢查操作
2菌瘫、每個Queue方法都有兩種形式:(1)如果操作失敗則拋出異常,(2)如果操作失敗布卡,則返回特殊值(null或false雨让,具體取決于操作),接口的常規(guī)結(jié)構(gòu)如下表所示忿等。
拋出異常 | 返回特殊值 | |
---|---|---|
插入 | add(e) | offer(e) |
刪除 | remove() | poll() |
檢查 | element() | peek() |
/**
* Queue是在處理之前保存元素的集合栖忠。除了基本的Collection操作外,Queue還提供額外的插入、刪除和檢查操作
* 每個Queue方法都有兩種形式:(1)如果操作失敗則拋出異常娃闲,
* (2)如果操作失敗虚汛,則返回特殊值(null或false,具體取決于操作)皇帮,接口的常規(guī)結(jié)構(gòu)如下表所示卷哩。
* 插入操作的后一種形式是專為使用有容量限制 Queue實(shí)現(xiàn);在大多數(shù)實(shí)現(xiàn)中属拾,插入操作不會失敗将谊。
*
* | | 拋出異常 | 返回特殊值 |
* |插入 | add(e) | offer(e) |
* |刪除 | remove() | poll() |
* |檢查 | element() | peek() |
*
* 隊(duì)列通常(但不一定)以FIFO(先進(jìn)先出)方式對元素進(jìn)行排序,優(yōu)先級隊(duì)列除外渐白,
* 它們根據(jù)元素的值對元素進(jìn)行排序 — 有關(guān)詳細(xì)信息尊浓,請參閱“對象排序”部分。
* 無論使用什么排序纯衍,隊(duì)列的頭部都是通過調(diào)用remove或poll移除的元素栋齿。
* 在FIFO隊(duì)列中,所有新元素都插入隊(duì)列的尾部襟诸,其他類型的隊(duì)列可能使用不同的放置規(guī)則瓦堵,
* 每個Queue實(shí)現(xiàn)都必須指定其排序?qū)傩浴? *
* Queue實(shí)現(xiàn)可以限制它所擁有的元素?cái)?shù)量,這樣的隊(duì)列被稱為有界歌亲,java.util.concurrent中的某些Queue實(shí)現(xiàn)是有界的菇用,但java.util中的實(shí)現(xiàn)不是。
* 可不只有拋出unchecked異常添加元素陷揪。的offer方法設(shè)計(jì)時使用的失敗是正常的惋鸥,
* 而不是特殊的情況,例如悍缠,固定容量(或“有界”)隊(duì)列卦绣。的remove()和poll()方法移除并返回隊(duì)列的頭部。
* 從隊(duì)列中刪除的是隊(duì)列的排序策略的函數(shù)飞蚓,它不同于從“實(shí)現(xiàn)”到“實(shí)現(xiàn)”的功能滤港。的remove()和poll()方法
* 只是他們的行為當(dāng)隊(duì)列為空的不同的remove()方法拋出一個異常,而poll()方法返回null玷坠。
*
* Queue從Collection繼承的add方法插入一個元素蜗搔,除非它違反了隊(duì)列的容量限制劲藐,
* 在這種情況下它會拋出IllegalStateException八堡。offer方法,僅用于有界隊(duì)列聘芜,
* 與add不同之處僅在于它通過返回false來表示插入元素失敗兄渺。
*
* remove和poll方法都移除并返回隊(duì)列的頭部,確切地移除哪個元素是隊(duì)列的排序策略的函數(shù)汰现,
* 僅當(dāng)隊(duì)列為空時挂谍,remove和poll方法的行為才有所不同叔壤,在這些情況下,
* remove拋出NoSuchElementException口叙,而poll返回null炼绘。
*
*element和peek方法返回但不移除隊(duì)列的頭部,它們之間的差異與remove和poll的方式完全相同:如果隊(duì)列為空妄田,則element拋出NoSuchElementException俺亮,而peek返回null。
* 隊(duì)列實(shí)現(xiàn)通常不允許插入null元素疟呐,為實(shí)現(xiàn)Queue而進(jìn)行了改進(jìn)的LinkedList實(shí)現(xiàn)是一個例外脚曾,
* 由于歷史原因,它允許null元素启具,但是你應(yīng)該避免利用它本讥,因?yàn)閚ull被poll和peek方法用作特殊的返回值。
*隊(duì)列實(shí)現(xiàn)通常不定義equals和hashCode方法的基于元素的版本鲁冯,而是從Object繼承基于標(biāo)識的版本拷沸。
* Queue接口不定義阻塞隊(duì)列方法,這在并發(fā)編程中很常見晓褪,這些等待元素出現(xiàn)或空間可用的方法在java.util.concurrent.BlockingQueue接口中定義堵漱,該接口擴(kuò)展了Queue。
*
*/
public interface Queue<E> extends Collection<E> {
/**
* 將指定的元素插入到此隊(duì)列中涣仿,如果不違反容量限制立即執(zhí)行此操作
* 成功后返回true勤庐,如果當(dāng)前沒有可用空間,則拋出IllegalStateException好港。
*/
boolean add(E e);
/**
* 如果在不違反容量限制的情況下立即執(zhí)行愉镰,則將指定的元素插入到此隊(duì)列中。
* 當(dāng)使用容量限制隊(duì)列時钧汹,此方法通常優(yōu)于add(E) 丈探,這可能無法僅通過拋出異常來插入元素。
* 成功返回true拔莱,失敗返回false
*/
boolean offer(E e);
/**
* 檢索并刪除此隊(duì)列的頭碗降。 此方法與poll不同之處在于,如果此隊(duì)列為空塘秦,它將拋出異常讼渊。
*/
E remove();
/**
* 檢索并刪除此隊(duì)列的頭,如果此隊(duì)列為空尊剔,則返回 null 爪幻。
*/
E poll();
/**
* 檢索,但不刪除,這個隊(duì)列的頭挨稿。 此方法與peek的不同之處在于仇轻,如果此隊(duì)列為空,它將拋出異常奶甘。
*/
E element();
/**
* 檢索但不刪除此隊(duì)列的頭部篷店,如果此隊(duì)列為空,則返回 null 臭家。
*/
E peek();
}
Queue接口特點(diǎn):
- 先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)船庇,即從容器的一端放入對象,從另一端取出侣监,并且對象放入容器的順序與取出的順序是相同的鸭轮。
- 雖然Queue接口繼承Collection接口,但是Queue接口中的方法都是獨(dú)立的橄霉,在創(chuàng)建具有Queue功能的實(shí)現(xiàn)時窃爷,不需要使用Collection方法。