日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java容器集合类的区别用法_Java容器笔记(二):不同集合实现类的特点与区别...

發(fā)布時間:2023/12/10 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java容器集合类的区别用法_Java容器笔记(二):不同集合实现类的特点与区别... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

package java.util包中的Collection相關(guān)接口和類如下圖:

Collection.png

僅討論Java.util包中的常見集合類,不涉及java.util的子包concurrent中的并發(fā)集合類。

可以這樣簡單的來對待容器中集合:

Collection_common.png

1、 List、Set、Queue三個接口的意義

首先,接口是一種規(guī)范,按照接口規(guī)范實現(xiàn)接口的的方法,就能提供所期望的功能。

三個接口只是規(guī)定了三類不同特性的集合,有時候?qū)崿F(xiàn)類會同時實現(xiàn)其中的多個特性,如LinkedList:

LinkedList.png

LinkedList既實現(xiàn)了List接口,又(間接)實現(xiàn)了Queue接口。它是List還是Queue呢?所以要理解這三個接口存在的意義。

List:元素有序,元素可重復(fù),添加的元素放在最后(按照插入順序保存元素)

//Appends the specified element to the end of this list

boolean add(E e);

List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數(shù)組下標(biāo))來訪問List中的元素,類似于Java的數(shù)組。List允許有相同的元素。除了具有Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個 ListIterator接口,和標(biāo)準(zhǔn)的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設(shè)定元素, 還能向前或向后進行雙向遍歷。

**Set:元素?zé)o序并且不允許重復(fù)元素 **

// If this set already contains the element, the call leaves the set

//unchanged and returns false. In combination with the

//restriction on constructors, this ensures that sets never contain

//duplicate elements.

boolean add(E e);

Set是一種不包含重復(fù)的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。

很明顯,Set的構(gòu)造函數(shù)有一個約束條件,傳入的Collection參數(shù)不能包含重復(fù)的元素。

請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態(tài)導(dǎo)致Object.equals(Object)=true將導(dǎo)致一些問題。

Queue:元素有序,先進先出

它們都是通過擴展Collection接口而來。Collection接口規(guī)范了存放一組對象的方式,而這組對象在存放時具有哪些特點(元素有序還是無序,元素允不允許重復(fù)等),則通過這三個接口進一步規(guī)范,實現(xiàn)了某個接口就具有某個接口規(guī)定的特性。而具體的實現(xiàn)方式的不同,使得各實現(xiàn)類的應(yīng)用場景不同。

2、各實現(xiàn)類的特點

先看List:

ArrayList

數(shù)據(jù)結(jié)構(gòu)為數(shù)組,訪問快(可以直接通過下標(biāo)訪問),增刪慢,未實現(xiàn)線程同步。

ArrayList實現(xiàn)了可變大小的數(shù)組。它允許所有元素,包括null。ArrayList沒有同步。size,isEmpty,get,set方法運行時間為常數(shù)。但是add方法開銷為分?jǐn)偟某?shù),添加n個元素需要O(n)的時間。其他的方法運行時間為線性。

每個ArrayList實例都有一個容量(Capacity),即用于存儲元素的數(shù)組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長算法 并沒有定義。當(dāng)需要插入大量元素時,在插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率。和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。

LinkedList

數(shù)據(jù)結(jié)構(gòu)為鏈表,增刪速度快,查詢慢,未實現(xiàn)線程同步

LinkedList實現(xiàn)了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在 LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。

Vector類

數(shù)據(jù)結(jié)構(gòu)為數(shù)組,訪問快(可以直接通過下標(biāo)訪問),增刪慢,實現(xiàn)線程同步

Vector非常類似ArrayList,但是Vector是同步的。由Vector創(chuàng)建的Iterator,雖然和 ArrayList創(chuàng)建的Iterator是同一接口,但是,因為Vector是同步的,當(dāng)一個Iterator被創(chuàng)建而且正在被使用,另一個線程改變了 Vector的狀態(tài)(例如,添加或刪除了一些元素),這時調(diào)用Iterator的方法時將拋出 ConcurrentModificationException。

再看Set

HashSet

數(shù)據(jù)結(jié)構(gòu)為哈希表,元素?zé)o序、不重復(fù),至多有一個null元素

底層使用 HashMap 來保存所有元素,因此 HashSet 的實現(xiàn)比較簡單,相關(guān) HashSet 的操作,基本上都是直接調(diào)用底層 HashMap 的相關(guān)方法來完成。

特點如下

? 不能保證元素的排列順序,順序有可能發(fā)生變化

? 不是同步的

? 集合元素可以是null,但只能放入一個null

當(dāng)向HashSet結(jié)合中存入一個元素時,HashSet會調(diào)用該對象的hashCode()方法來得到該對象的hashCode值,然后根據(jù) hashCode值來決定該對象在HashSet中存儲位置。

簡單的說,HashSet集合判斷兩個元素相等的標(biāo)準(zhǔn)是兩個對象通過equals方法比較相等,并且兩個對象的hashCode()方法返回值相 等

注意,如果要把一個對象放入HashSet中,重寫該對象對應(yīng)類的equals方法,也應(yīng)該重寫其hashCode()方法。其規(guī)則是如果兩個對 象通過equals方法比較返回true時,其hashCode也應(yīng)該相同。另外,對象中用作equals比較標(biāo)準(zhǔn)的屬性,都應(yīng)該用來計算 hashCode的值。

LinkedHashSet

數(shù)據(jù)結(jié)構(gòu)是哈希表和鏈表,與HashSet相比訪問更快,插入時性能稍微

LinkedHashSet繼承自HashSet。同樣是根據(jù)元素的hashCode值來決定元素的存儲位置,但是它同時使用鏈表維護元素的次序。這樣使得元素看起 來像是以插入順序保存的,也就是說,當(dāng)遍歷該集合時候,LinkedHashSet將會以元素的添加順序訪問集合的元素。

LinkedHashSet在迭代訪問Set中的全部元素時,性能比HashSet好,但是插入時性能稍微遜色于HashSet。

TreeSet

數(shù)據(jù)結(jié)構(gòu)是二叉樹(紅黑樹),元素可排序、不重復(fù)

TreeSet是SortedSet接口的唯一實現(xiàn)類,TreeSet可以確保集合元素處于排序狀態(tài)。TreeSet支持兩種排序方式:自然排序和定制排序,其中自然排序為默認(rèn)的排序方式。向TreeSet中加入的應(yīng)該是同一個類的對象。

TreeSet判斷兩個對象不相等的方式是兩個對象通過equals方法返回false,或者通過CompareTo方法比較沒有返回0

自然排序

(1)TreeSet內(nèi)的元素實現(xiàn)Comparable接口,重寫該接口的compareTo(Object obj)方法,以此確定排序。(元素必須實現(xiàn)該接口,否則程序會拋出異常)。

(2)當(dāng)重寫元素對應(yīng)類的equals()方法時,應(yīng)該保證該方法與compareTo(Object obj)方法有一致的結(jié)果,即如果兩個對象通過equals()方法比較返回true時,這兩個對象通過compareTo(Object obj)方法比較結(jié)果應(yīng)該也為0(即相等)

定制排序--

自然排序是根據(jù)集合元素的大小,以升序排列,如果要定制排序,應(yīng)該使用Comparator接口,實現(xiàn)int compare(T o1,T o2)方法

個人看法:兩種方式都是為了排序,一種是元素本身實現(xiàn)`Comparable`接口,另一種則是當(dāng)元素本身沒有實現(xiàn)`Comparable`接口時,可以通過`Comparator`接口(傳入構(gòu)造器`TreeSet(Comparator comparator)`),兩者本身沒有什么區(qū)別。

Java : Comparable vs Comparator

In short, there isn't much difference. They are both ends to similar means. In general implement comparable for natural order, (natural order definition is obviously open to interpretation), and write a comparator for other sorting or comparison needs.

最后看Queue

ArrayDeque

數(shù)據(jù)結(jié)構(gòu)為數(shù)組,雙端隊列,在隊頭隊尾均可心插入或刪除元素

實現(xiàn)了DeQueue接口。DeQueue(Double-ended queue)繼承了Queue接口,創(chuàng)建雙向隊列,靈活性更強,可以前向或后向迭代,

ArrayDeque.png

PriorityQueue

數(shù)據(jù)結(jié)構(gòu)為優(yōu)先級隊列,元素不允許null,非同步

優(yōu)先級隊列是一種什么樣的數(shù)據(jù)結(jié)構(gòu)

優(yōu)先級隊列是不同于先進先出隊列的另一種隊列。每次從隊列中取出的是具有最高優(yōu)先權(quán)的元素。

(1)優(yōu)先級隊列不是同步的(線程安全版本為PriorityBlockingQueue)

隊列的獲取操作如poll(),peek()和element()是訪問的隊列的頭,保證獲取的是最小的元素(根據(jù)指定的排序規(guī)則)

(2)返回的迭代器并不保證提供任何的有序性

(3)優(yōu)先級隊列不允許null元素,否則拋出NullPointException。

3、有助于理解的問答

遍歷一個List有哪些不同的方式?

List strList = new ArrayList<>();

//使用for-each循環(huán)

for(String obj : strList){

System.out.println(obj);

}

//using iterator

Iterator it = strList.iterator();

while(it.hasNext()){

String obj = it.next();

System.out.println(obj);

}

使用迭代器更加線程安全,因為它可以確保,在當(dāng)前遍歷的集合元素被更改的時候,它會拋出ConcurrentModificationException。

在迭代一個集合的時候,如何避免ConcurrentModificationException?

在遍歷一個集合的時候,我們可以使用并發(fā)集合類來避免ConcurrentModificationException,比如使用CopyOnWriteArrayList,而不是ArrayList。

4、常見面試題

List和Set的區(qū)別

List有序,允許重復(fù),Set無序,不允許重復(fù)

ArrayList與LinkedList的區(qū)別

ArrayList為數(shù)組結(jié)構(gòu),LinkedList為鏈表結(jié)構(gòu)。所以,一個訪問快,一個增刪快。均未實現(xiàn)線程同步或者說都是線程不安全的。

(1)ArrayList是由Array所支持的基于一個索引的數(shù)據(jù)結(jié)構(gòu),所以它提供對元素的隨機訪問,復(fù)雜度為O(1),但LinkedList存儲一系列的節(jié)點數(shù)據(jù),每個節(jié)點都與前一個和下一個節(jié)點相連接。所以,盡管有使用索引獲取元素的方法,內(nèi)部實現(xiàn)是從起始點開始遍歷,遍歷到索引的節(jié)點然后返回元素,時間復(fù)雜度為O(n),比ArrayList要慢。

(2)與ArrayList相比,在LinkedList中插入、添加和刪除一個元素會更快,因為在一個元素被插入到中間的時候,不會涉及改變數(shù)組的大小,或更新索引。

(3)LinkedList比ArrayList消耗更多的內(nèi)存,因為LinkedList中的每個節(jié)點存儲了前后節(jié)點的引用。

ArrayList與Vector的區(qū)別

Vector同步,ArrayList不同步。

ArrayList和Vector在很多時候都很類似。

(1)兩者都是基于索引的,內(nèi)部由一個數(shù)組支持。

(2)兩者維護插入的順序,我們可以根據(jù)插入順序來獲取元素。

(3)ArrayList和Vector的迭代器實現(xiàn)都是fail-fast的。

(4)ArrayList和Vector兩者允許null值,也可以使用索引值對元素進行隨機訪問。

以下是ArrayList和Vector的不同點。

(1)Vector是同步的,而ArrayList不是。然而,如果你尋求在迭代的時候?qū)α斜磉M行改變,你應(yīng)該使用CopyOnWriteArrayList。

(2)ArrayList比Vector快,它因為有同步,不會過載。

(3)ArrayList更加通用,因為我們可以使用Collections工具類輕易地獲取同步列表和只讀列表。

Array和ArrayList有何區(qū)別?什么時候更適合用Array?

Array可以容納基本類型和對象,而ArrayList只能容納對象。

Array是指定大小的,而ArrayList大小是不固定的。

Array沒有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。盡管ArrayList明顯是更好的選擇,但也有些時候Array比較好用。

(1)如果列表的大小已經(jīng)指定,大部分情況下是存儲和遍歷它們。

(2)對于遍歷基本數(shù)據(jù)類型,盡管Collections使用自動裝箱來減輕編碼任務(wù),在指定大小的基本類型的列表上工作也會變得很慢。

(3)如果你要使用多維數(shù)組,使用[][]比List>更容易。

5、簡單總結(jié)

如果元素唯一(不允許重復(fù)),使用Set:

支持排序則選擇TreeSet,不支持排序選擇HashSet。

如果元素不唯一(允許重復(fù)),使用List:

查詢多則選擇ArrayList,增刪多則選擇:LinkedList。

Vector雖然是ArrayList的線程同步版本,但還有更好地選擇。

關(guān)于Queue,由于工作中從未接觸過,待補充。

參考

未一一列出,待補充

總結(jié)

以上是生活随笔為你收集整理的java容器集合类的区别用法_Java容器笔记(二):不同集合实现类的特点与区别...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。