Java集合框架總結(jié)

簡(jiǎn)介

集合框架:用于存儲(chǔ)數(shù)據(jù)的容器。

集合框架是為表示和操作集合而規(guī)定的一種統(tǒng)一的標(biāo)準(zhǔn)的體系結(jié)構(gòu)码邻。
任何集合框架都包含三大塊內(nèi)容:對(duì)外的接口折剃、接口的實(shí)現(xiàn)和對(duì)集合運(yùn)算的算法。

接口:表示集合的抽象數(shù)據(jù)類(lèi)型像屋。接口允許我們操作集合時(shí)不必關(guān)注具體實(shí)現(xiàn)怕犁,從而達(dá)到“多態(tài)”。在面向?qū)ο缶幊陶Z(yǔ)言中,接口通常用來(lái)形成規(guī)范奏甫。

實(shí)現(xiàn):集合接口的具體實(shí)現(xiàn)戈轿,是重用性很高的數(shù)據(jù)結(jié)構(gòu)。

算法:在一個(gè)實(shí)現(xiàn)了某個(gè)集合框架中的接口的對(duì)象身上完成某種有用的計(jì)算的方法扶檐,例如查找凶杖、排序等胁艰。這些算法通常是多態(tài)的款筑,因?yàn)橄嗤姆椒梢栽谕粋€(gè)接口被多個(gè)類(lèi)實(shí)現(xiàn)時(shí)有不同的表現(xiàn)。事實(shí)上腾么,算法是可復(fù)用的函數(shù)奈梳。
它減少了程序設(shè)計(jì)的辛勞。

集合框架通過(guò)提供有用的數(shù)據(jù)結(jié)構(gòu)和算法使你能集中注意力于你的程序的重要部分上解虱,而不是為了讓程序能正常運(yùn)轉(zhuǎn)而將注意力于低層設(shè)計(jì)上攘须。
通過(guò)這些在無(wú)關(guān)API之間的簡(jiǎn)易的互用性,使你免除了為改編對(duì)象或轉(zhuǎn)換代碼以便聯(lián)合這些API而去寫(xiě)大量的代碼殴泰。 它提高了程序速度和質(zhì)量于宙。

特點(diǎn)

  • 對(duì)象封裝數(shù)據(jù),對(duì)象多了也需要存儲(chǔ)悍汛。集合用于存儲(chǔ)對(duì)象捞魁。

  • 對(duì)象的個(gè)數(shù)確定可以使用數(shù)組,對(duì)象的個(gè)數(shù)不確定的可以用集合离咐。因?yàn)榧鲜强勺冮L(zhǎng)度的谱俭。

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

  • 數(shù)組是固定長(zhǎng)度的;集合可變長(zhǎng)度的宵蛀。

  • 數(shù)組可以存儲(chǔ)基本數(shù)據(jù)類(lèi)型昆著,也可以存儲(chǔ)引用數(shù)據(jù)類(lèi)型;集合只能存儲(chǔ)引用數(shù)據(jù)類(lèi)型术陶。

  • 數(shù)組存儲(chǔ)的元素必須是同一個(gè)數(shù)據(jù)類(lèi)型凑懂;集合存儲(chǔ)的對(duì)象可以是不同數(shù)據(jù)類(lèi)型。

數(shù)據(jù)結(jié)構(gòu):就是容器中存儲(chǔ)數(shù)據(jù)的方式梧宫。

對(duì)于集合容器征候,有很多種。因?yàn)槊恳粋€(gè)容器的自身特點(diǎn)不同祟敛,其實(shí)原理在于每個(gè)容器的內(nèi)部數(shù)據(jù)結(jié)構(gòu)不同疤坝。

集合容器在不斷向上抽取過(guò)程中,出現(xiàn)了集合體系馆铁。在使用一個(gè)體系的原則:參閱頂層內(nèi)容跑揉。建立底層對(duì)象。

使用集合框架的好處

  1. 容量自增長(zhǎng);
  2. 提供了高性能的數(shù)據(jù)結(jié)構(gòu)和算法历谍,使編碼更輕松现拒,提高了程序速度和質(zhì)量;
  3. 允許不同 API 之間的互操作望侈,API之間可以來(lái)回傳遞集合印蔬;
  4. 可以方便地?cái)U(kuò)展或改寫(xiě)集合,提高代碼復(fù)用性和可操作性脱衙。
  5. 通過(guò)使用JDK自帶的集合類(lèi)侥猬,可以降低代碼維護(hù)和學(xué)習(xí)新API成本。

Iterator接口

Iterator接口捐韩,用于遍歷集合元素的接口退唠。

在Iterator接口中定義了三個(gè)方法:

修飾與類(lèi)型 方法與描述
boolean hasNext() 如果仍有元素可以迭代,則返回true荤胁。
E next() 返回迭代的下一個(gè)元素瞧预。
void remove() 從迭代器指向的 collection 中移除迭代器返回的最后一個(gè)元素(可選操作)。

每一個(gè)集合都有自己的數(shù)據(jù)結(jié)構(gòu)(就是容器中存儲(chǔ)數(shù)據(jù)的方式)仅政,都有特定的取出自己內(nèi)部元素的方式垢油。為了便于操作所有的容器,取出元素圆丹。將容器內(nèi)部的取出方式按照一個(gè)統(tǒng)一的規(guī)則向外提供滩愁,這個(gè)規(guī)則就是Iterator接口,使得對(duì)容器的遍歷操作與其具體的底層實(shí)現(xiàn)相隔離运褪,達(dá)到解耦的效果惊楼。

也就說(shuō),只要通過(guò)該接口就可以取出Collection集合中的元素秸讹,至于每一個(gè)具體的容器依據(jù)自己的數(shù)據(jù)結(jié)構(gòu)檀咙,如何實(shí)現(xiàn)的具體取出細(xì)節(jié),這個(gè)不用關(guān)心璃诀,這樣就降低了取出元素和具體集合的耦合性弧可。

使用迭代器遍歷集合元素

 public static void main(String[] args) { 
   List<String> list1 = new ArrayList<>(); 
    list1.add("abc0"); 
    list1.add("abc1");
    list1.add("abc2"); 
    // while循環(huán)方式遍歷
    Iterator it1 = list1.iterator(); 
    while (it1.hasNext()) {
        System.out.println(it1.next());
    }
    // for循環(huán)方式遍歷   
 for (Iterator it2 = list1.iterator(); it2.hasNext(); ) {
        System.out.println(it2.next());
    }
}

使用Iterator迭代器進(jìn)行刪除集合元素,則不會(huì)出現(xiàn)并發(fā)修改異常劣欢。

因?yàn)椋涸趫?zhí)行remove操作時(shí)棕诵,同樣先執(zhí)行checkForComodification(),然后會(huì)執(zhí)行ArrayList的remove()方法凿将,該方法會(huì)將modCount值加1校套,這里我們將expectedModCount=modCount,使之保持統(tǒng)一牧抵。

ListIterator接口

ListIterator是一個(gè)功能更加強(qiáng)大的迭代器笛匙, 它繼承于Iterator接口侨把,只能用于各種List類(lèi)型的訪問(wèn)∶盟铮可以通過(guò)調(diào)用listIterator()方法產(chǎn)生一個(gè)指向List開(kāi)始處的ListIterator秋柄, 還可以調(diào)用listIterator(n)方法創(chuàng)建一個(gè)一開(kāi)始就指向列表索引為n的元素處的ListIterator。

特點(diǎn)

  1. 允許我們向前蠢正、向后兩個(gè)方向遍歷 List骇笔;
  2. 在遍歷時(shí)修改 List 的元素;
  3. 遍歷時(shí)獲取迭代器當(dāng)前游標(biāo)所在位置嚣崭。

常用API

修飾與類(lèi)型 方法與描述
void add(E e) 將指定的元素插入到列表 (可選操作)笨触。
boolean hasNext() 如果此列表迭代器在前進(jìn)方向還有更多的元素時(shí),返回 true有鹿。
boolean hasPrevious() 如果此列表迭代器在相反方向還有更多的元素時(shí)旭旭,返回 true谎脯。
E next() 返回列表中的下一個(gè)元素和光標(biāo)的位置向后推進(jìn)葱跋。
int nextIndex() 返回調(diào)用 next()后返回的元素索引。
E previous() 返回列表中的上一個(gè)元素和光標(biāo)的位置向前移動(dòng)源梭。
int previousIndex() 返回調(diào)用previous() 后返回的元素索引 娱俺。
void remove() 刪除列表中調(diào)用next()previous()的返回最后一個(gè)元素。
void set(E e) 用指定元素替換列表中調(diào)用next()previous()的返回最后一個(gè)元素废麻。

Collection接口

所有集合類(lèi)都位于java.util包下荠卷。Java的集合類(lèi)主要由兩個(gè)接口派生而出:CollectionMap,Collection和Map是Java集合框架的根接口烛愧,這兩個(gè)接口又包含了一些子接口或?qū)崿F(xiàn)類(lèi)油宜。

  • Collection一次存一個(gè)元素,是單列集合怜姿;

  • Map一次存一對(duì)元素慎冤,是雙列集合。Map存儲(chǔ)的一對(duì)元素:鍵–值沧卢,鍵(key)與值(value)間有對(duì)應(yīng)(映射)關(guān)系蚁堤。

單列集合繼承關(guān)系圖

單列集合

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">單列集合</figcaption>

Collection集合主要有List和Set兩大接口

  • List:有序(元素存入集合的順序和取出的順序一致),元素都有索引但狭。元素可以重復(fù)披诗。

  • Set:無(wú)序(存入和取出順序有可能不一致),不可以存儲(chǔ)重復(fù)元素立磁。必須保證元素唯一性呈队。

List集合

List是元素有序并且可以重復(fù)的集合。

List的主要實(shí)現(xiàn):ArrayList唱歧, LinkedList宪摧, Vector。

List常用方法

[圖片上傳失敗...(image-db0f89-1590065528899)]

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">List常用方法</figcaption>

ArrayList、LinkedList绍刮、Vector 的區(qū)別
ArrayList LinkedList Vector
底層實(shí)現(xiàn) 數(shù)組 雙向鏈表 數(shù)組
同步性及效率 不同步温圆,非線(xiàn)程安全,效率高孩革,支持隨機(jī)訪問(wèn) 不同步岁歉,非線(xiàn)程安全,效率高 同步膝蜈,線(xiàn)程安全锅移,效率低
特點(diǎn) 查詢(xún)快,增刪慢 查詢(xún)慢饱搏,增刪快 查詢(xún)快非剃,增刪慢
默認(rèn)容量 10 / 10
擴(kuò)容機(jī)制 int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5 倍 / 2 倍

總結(jié)

  • ArrayList 和 Vector 基于數(shù)組實(shí)現(xiàn)推沸,對(duì)于隨機(jī)訪問(wèn)get和set备绽,ArrayList優(yōu)于LinkedList,因?yàn)長(zhǎng)inkedList要移動(dòng)指針鬓催。
  • LinkedList 不會(huì)出現(xiàn)擴(kuò)容的問(wèn)題肺素,所以比較適合隨機(jī)位置增、刪宇驾。但是其基于鏈表實(shí)現(xiàn)倍靡,所以在定位時(shí)需要線(xiàn)性?huà)呙瑁时容^低课舍。
  • 當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間塌西,并且需要隨機(jī)地訪問(wèn)其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能筝尾;
  • 當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù)捡需,并且按照順序訪問(wèn)其中的元素時(shí),就應(yīng)該使用LinkedList了忿等。
遍歷時(shí)操作元素

遍歷集合時(shí)栖忠,同時(shí)操作集合中的元素(增刪等)

 1/**
* Description: for循環(huán)遍歷 
  * 輸出結(jié)果: 
  * [a, b, c, d, e] 
  * 由結(jié)果可知,第二個(gè)元素b并未刪除贸街,原因是當(dāng)?shù)谝粋€(gè)元素b被刪除后庵寞,它后面所有的元素都向前移動(dòng)了一個(gè)單位,循環(huán)時(shí)導(dǎo)致第二個(gè)元素b漏掉了 
  */ 
public static void remove(List<String> list) { 
    for (int i = 0; i < list.size(); i++) { 
        String s = list.get(i);
        if (s.equals("b")) {
            list.remove(s);
        }
    }
}
/**
  * Description: foreach循環(huán)遍歷
  *
  * 會(huì)報(bào)錯(cuò):java.util.ConcurrentModificationException薛匪。這是因?yàn)樵谶@里捐川,foreach循環(huán)遍歷容器本質(zhì)上是使用迭代器進(jìn)行遍歷的,會(huì)對(duì)修改次數(shù)modCount進(jìn)行檢查逸尖,不允許集合進(jìn)行更改操作
    */
public static void remove2(List<String> list) {
    for (String s : list) {
        if (s.equals("b")) {
            list.remove(s);
       }
        System.out.println(s);
    }
}
/**
  * Description: 使用迭代器遍歷
  */
public static void remove3(List<String> list) {
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
       String s = it.next();
        if (s.equals("b")) {
            it.remove();
       }
    }
}

使用迭代器遍歷刪除時(shí)古沥,能夠避免方法二中出現(xiàn)的問(wèn)題瘸右。這是因?yàn)椋涸贏rrayList中,modCount是指集合的修改次數(shù)岩齿,當(dāng)進(jìn)行add或者delete時(shí)太颤,modCount會(huì)+1;expectedModCount是指集合的迭代器的版本號(hào)盹沈,初始值是modCount龄章,但是當(dāng)集合進(jìn)行add或者delete操作時(shí),modCount會(huì)+1乞封,而expectedModCount不會(huì)改變做裙,所以方法二中會(huì)拋出異常。但是it.remove操作時(shí)肃晚,會(huì)同步expectedModCount的值锚贱,把modCount的值賦予expectedModCount。所以不會(huì)拋出異常关串。

測(cè)試方法

 1public static void main(String[] args) { 
    List<String> arrayList = new ArrayList<String>(); 
    arrayList.add("a"); 
   arrayList.add("b"); 
    arrayList.add("b"); 
    arrayList.add("c"); 
    arrayList.add("d"); 
    arrayList.add("e"); 
    // remove(arrayList);
    // remove2(arrayList);
    remove3(arrayList);
    System.out.println(arrayList);
}

總結(jié):如果想正確的循環(huán)遍歷刪除(增加)元素拧廊,需要使用方法三,也就是迭代器遍歷刪除(增加)的方法悍缠。

Set集合

Set集合元素?zé)o序(存入和取出的順序不一定一致)卦绣,并且沒(méi)有重復(fù)對(duì)象耐量。
Set的主要實(shí)現(xiàn)類(lèi):HashSet飞蚓, TreeSet。

Set常用方法

[圖片上傳失敗...(image-960be-1590065528899)]

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">Set常用方法</figcaption>

HashSet廊蜒、TreeSet趴拧、LinkedHashSet的區(qū)別
HashSet TreeSet LinkedHashSet
底層實(shí)現(xiàn) HashMap 紅黑樹(shù) LinkedHashMap
重復(fù)性 不允許重復(fù) 不允許重復(fù) 不允許重復(fù)
有無(wú)序 無(wú)序 有序,支持兩種排序方式山叮,自然排序和定制排序著榴,其中自然排序?yàn)槟J(rèn)的排序方式。 有序屁倔,以元素插入的順序來(lái)維護(hù)集合的鏈接表
時(shí)間復(fù)雜度 add()脑又,remove(),contains()方法的時(shí)間復(fù)雜度是O(1) add()锐借,remove()问麸,contains()方法的時(shí)間復(fù)雜度是O(logn) LinkedHashSet在迭代訪問(wèn)Set中的全部元素時(shí),性能比HashSet好钞翔,但是插入時(shí)性能稍微遜色于HashSet严卖,時(shí)間復(fù)雜度是 O(1)。
同步性 不同步布轿,線(xiàn)程不安全 不同步哮笆,線(xiàn)程不安全 不同步来颤,線(xiàn)程不安全
null值 允許null值 不支持null值,會(huì)拋出 java.lang.NullPointerException 異常稠肘。因?yàn)門(mén)reeSet應(yīng)用 compareTo() 方法于各個(gè)元素來(lái)比較他們福铅,當(dāng)比較null值時(shí)會(huì)拋出 NullPointerException異常。 允許null值
比較 equals() compareTo() equals()
HashSet如何檢查重復(fù)

當(dāng)你把對(duì)象加入HashSet時(shí)项阴,HashSet會(huì)先計(jì)算對(duì)象的hashcode值來(lái)判斷對(duì)象加入的位置本讥,同時(shí)也會(huì)與其他加入的對(duì)象的hashcode值作比較,如果沒(méi)有相符的hashcode鲁冯,HashSet會(huì)假設(shè)對(duì)象沒(méi)有重復(fù)出現(xiàn)拷沸。但是如果發(fā)現(xiàn)有相同hashcode值的對(duì)象,這時(shí)會(huì)調(diào)用equals()方法來(lái)檢查hashcode相等的對(duì)象是否真的相同薯演。如果兩者相同撞芍,HashSet就不會(huì)讓加入操作成功。
hashCode()與equals()的相關(guān)規(guī)定:

  • 如果兩個(gè)對(duì)象相等跨扮,則hashcode一定也是相同的
  • 兩個(gè)對(duì)象相等序无,equals方法返回true
  • 兩個(gè)對(duì)象有相同的hashcode值,它們也不一定是相等的
  • 綜上衡创,equals方法被覆蓋過(guò)帝嗡,則hashCode方法也必須被覆蓋
    hashCode()的默認(rèn)行為是對(duì)堆上的對(duì)象產(chǎn)生獨(dú)特值。如果沒(méi)有重寫(xiě)hashCode()璃氢,則該class的兩個(gè)對(duì)象無(wú)論如何都不會(huì)相等(即使這兩個(gè)對(duì)象指向相同的數(shù)據(jù))哟玷。

總結(jié):
HashSet是一個(gè)通用功能的Set,而LinkedHashSet 提供元素插入順序保證一也,TreeSet是一個(gè)SortedSet實(shí)現(xiàn)巢寡,由Comparator 或者 Comparable指定的元素順序存儲(chǔ)元素。

Map接口

Map 是一種把鍵對(duì)象和值對(duì)象映射的集合椰苟,它的每一個(gè)元素都包含一對(duì)鍵對(duì)象和值對(duì)象抑月。 Map沒(méi)有繼承于Collection接口,從Map集合中檢索元素時(shí)舆蝴,只要給出鍵對(duì)象谦絮,就會(huì)返回對(duì)應(yīng)的值對(duì)象。
Map 的常用實(shí)現(xiàn)類(lèi):HashMap洁仗、TreeMap层皱、HashTable、LinkedHashMap京痢、ConcurrentHashMap

雙列集合繼承關(guān)系圖

雙列集合

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">雙列集合</figcaption>

Map常用方法

[圖片上傳失敗...(image-211757-1590065528899)]

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">Map常用方法</figcaption>

HashMap奶甘、HashTable、TreeMap的區(qū)別

  • TreeMap:基于紅黑樹(shù)實(shí)現(xiàn)祭椰。
  • HashMap:基于哈希表實(shí)現(xiàn)臭家。
  • HashTable:和 HashMap 類(lèi)似疲陕,但它是線(xiàn)程安全的,這意味著同一時(shí)刻多個(gè)線(xiàn)程可以同時(shí)寫(xiě)入 HashTable 并且不會(huì)導(dǎo)致數(shù)據(jù)不一致钉赁。它是遺留類(lèi)蹄殃,不應(yīng)該去使用它。現(xiàn)在可以使用 ConcurrentHashMap 來(lái)支持線(xiàn)程安全你踩,并且 ConcurrentHashMap 的效率會(huì)更高诅岩,因?yàn)?ConcurrentHashMap 引入了分段鎖。
  • LinkedHashMap:使用雙向鏈表來(lái)維護(hù)元素的順序带膜,順序?yàn)椴迦腠樞蚧蛘咦罱钌偈褂茫↙RU)順序吩谦。
HashMap HashTable TreeMap
底層實(shí)現(xiàn) 哈希表(數(shù)組+鏈表) 哈希表(數(shù)組+鏈表) 紅黑樹(shù)
同步性 線(xiàn)程不同步 同步 線(xiàn)程不同步
null值 允許 key 和 Vale 是 null,但是只允許一個(gè) key 為 null膝藕,且這個(gè)元素存放在哈希表 0 角標(biāo)位置 不允許key式廷、value 是 null value允許為null。

當(dāng)未實(shí)現(xiàn) Comparator 接口時(shí)芭挽,key 不可以為null
當(dāng)實(shí)現(xiàn) Comparator 接口時(shí)滑废,若未對(duì) null 情況進(jìn)行判斷,則可能拋 NullPointerException 異常袜爪。如果針對(duì)null情況實(shí)現(xiàn)了蠕趁,可以存入,但是卻不能正常使用get()訪問(wèn)辛馆,只能通過(guò)遍歷去訪問(wèn)俺陋。 |
| hash | 使用hash(Object key)擾動(dòng)函數(shù)對(duì) key 的 hashCode 進(jìn)行擾動(dòng)后作為 hash 值 | 直接使用 key 的 hashCode() 返回值作為 hash 值 | |
| 容量 | 容量為 2^4 且容量一定是 2^n | 默認(rèn)容量是11,不一定是 2^n | |
| 擴(kuò)容 | 兩倍怀各,且哈希桶的下標(biāo)使用 &運(yùn)算代替了取模 | 2倍+1倔韭,取哈希桶下標(biāo)是直接用模運(yùn)算 | |

HashMap在JDK1.7和JDK1.8中有哪些不同

不同 JDK 1.7 JDK 1.8
存儲(chǔ)結(jié)構(gòu) 數(shù)組 + 鏈表 數(shù)組 + 鏈表 + 紅黑樹(shù)
初始化方式 單獨(dú)函數(shù):inflateTable() 直接集成到了擴(kuò)容函數(shù)resize()
hash值計(jì)算方式 擾動(dòng)處理 = 9次擾動(dòng) = 4次位運(yùn)算 + 5次異或運(yùn)算 擾動(dòng)處理 = 2次擾動(dòng) = 1次位運(yùn)算 + 1次異或運(yùn)算
存放數(shù)據(jù)的規(guī)則 無(wú)沖突時(shí),存放數(shù)組瓢对;沖突時(shí),存放鏈表 無(wú)沖突時(shí)胰苏,存放數(shù)組硕蛹;沖突 & 鏈表長(zhǎng)度 < 8:存放單鏈表;沖突 & 鏈表長(zhǎng)度 > 8:樹(shù)化并存放紅黑樹(shù)
插入數(shù)據(jù)方式 頭插法(先講原位置的數(shù)據(jù)移到后1位硕并,再插入數(shù)據(jù)到該位置) 尾插法(直接插入到鏈表尾部/紅黑樹(shù))
擴(kuò)容后存儲(chǔ)位置的計(jì)算方式 全部按照原來(lái)方法進(jìn)行計(jì)算(即hashCode ->> 擾動(dòng)函數(shù) ->> (h&length-1)) 按照擴(kuò)容后的規(guī)律計(jì)算(即擴(kuò)容后的位置=原位置 or 原位置 + 舊容量)

集合工具類(lèi)Collections

Collections:集合工具類(lèi)法焰,方便對(duì)集合的操作。這個(gè)類(lèi)不需要?jiǎng)?chuàng)建對(duì)象倔毙,內(nèi)部提供的都是靜態(tài)方法埃仪。

靜態(tài)方法:

Collections.sort(list);//list集合進(jìn)行元素的自然順序排序。
Collections.sort(list,new ComparatorByLen());//按指定的比較器方法排序陕赃。
class ComparatorByLen implements Comparator<String>{
  public int compare(String s1,String s2){
     int temp = s1.length()-s2.length();
     return temp==0?s1.compareTo(s2):temp;
  }
}
Collections.max(list);//返回list中字典順序最大的元素卵蛉。
int index = Collections.binarySearch(list,"zz");//二分查找颁股,返回角標(biāo)。
Collections.reverseOrder();//逆向反轉(zhuǎn)排序傻丝。
Collections.shuffle(list);//隨機(jī)對(duì)list中的元素進(jìn)行位置的置換甘有。

//將非同步集合轉(zhuǎn)成同步集合的方法:Collections中的  XXX synchronizedXXX(XXX);  
//原理:定義一個(gè)類(lèi),將集合所有的方法加同一把鎖后返回葡缰。
List synchronizedList(list);
Map synchronizedMap(map);

Collection 和 Collections的區(qū)別

  Collections是個(gè)java.util下的類(lèi)亏掀,是針對(duì)集合類(lèi)的一個(gè)工具類(lèi),提供一系列靜態(tài)方法,實(shí)現(xiàn)對(duì)集合的查找、排序泛释、替換滤愕、線(xiàn)程安全化(將非同步的集合轉(zhuǎn)換成同步的)等操作。

  Collection是個(gè)java.util下的接口怜校,它是各種集合結(jié)構(gòu)的父接口该互,繼承于它的接口主要有Set和List,提供了關(guān)于集合的一些操作,如插入、刪除韭畸、判斷一個(gè)元素是否其成員宇智、遍歷等。

數(shù)組工具類(lèi) Arrays

用于操作數(shù)組對(duì)象的工具類(lèi)胰丁,里面都是靜態(tài)方法随橘。

數(shù)組 -> 集合:asList方法,將數(shù)組轉(zhuǎn)換成list集合锦庸。

String[] arr ={"abc","kk","qq"};
List<String> list =Arrays.asList(arr);//將arr數(shù)組轉(zhuǎn)成list集合机蔗。

將數(shù)組轉(zhuǎn)換成集合,有什么好處呢甘萧?用aslist方法萝嘁,將數(shù)組變成集合;

可以通過(guò)list集合中的方法來(lái)操作數(shù)組中的元素:isEmpty()扬卷、contains牙言、indexOf、set怪得;

注意(局限性):數(shù)組是固定長(zhǎng)度咱枉,不可以使用集合對(duì)象增加或者刪除等,會(huì)改變數(shù)組長(zhǎng)度的功能方法徒恋。比如add蚕断、remove、clear入挣。(會(huì)報(bào)不支持操作異常UnsupportedOperationException)亿乳;

如果數(shù)組中存儲(chǔ)的引用數(shù)據(jù)類(lèi)型,直接作為集合的元素可以直接用集合方法操作径筏。

如果數(shù)組中存儲(chǔ)的是基本數(shù)據(jù)類(lèi)型葛假,asList會(huì)將數(shù)組實(shí)體作為集合元素存在障陶。

集合 -> 數(shù)組:用的是Collection接口中的toArray()方法;

如果給toArray傳遞的指定類(lèi)型的數(shù)據(jù)長(zhǎng)度小于了集合的size,那么toArray方法桐款,會(huì)自定再創(chuàng)建一個(gè)該類(lèi)型的數(shù)據(jù)咸这,長(zhǎng)度為集合的size。

如果傳遞的指定的類(lèi)型的數(shù)組的長(zhǎng)度大于了集合的size魔眨,那么toArray方法媳维,就不會(huì)創(chuàng)建新數(shù)組,直接使用該數(shù)組即可遏暴,并將集合中的元素存儲(chǔ)到數(shù)組中侄刽,其他為存儲(chǔ)元素的位置默認(rèn)值null。

所以朋凉,在傳遞指定類(lèi)型數(shù)組時(shí)州丹,最好的方式就是指定的長(zhǎng)度和size相等的數(shù)組。

將集合變成數(shù)組后有什么好處杂彭?限定了對(duì)集合中的元素進(jìn)行增刪操作墓毒,只要獲取這些元素即可。

用基本數(shù)據(jù)類(lèi)型的數(shù)組轉(zhuǎn)換ArrayList亲怠,ArrayList的size有問(wèn)題

public static void main(String[] args) {
    int[] arr1 = { 1, 2, 3, 4, 5 };
    List<int[]> intList = Arrays.asList(arr1);
    // intList size: 1
    System.out.println(String.format("intList size: %s", intList.size()));

    Integer[] arr2 = { 1, 2, 3, 4, 5 };
    List<Integer> integerList = Arrays.asList(arr2);
    // integerList size: 5
    System.out.println(String.format("integerList size:%s", integerList.size()));
}

asList方法接受的參數(shù)是一個(gè)泛型的變長(zhǎng)參數(shù)所计,我們知道基本數(shù)據(jù)類(lèi)型是無(wú)法泛型化的,也就是說(shuō)基本類(lèi)型是無(wú)法作為asList方法的參數(shù)的团秽, 要想作為泛型參數(shù)就必須使用其所對(duì)應(yīng)的包裝類(lèi)型主胧。但是這個(gè)這個(gè)實(shí)例中為什么沒(méi)有出錯(cuò)呢?因?yàn)樵搶?shí)例是將int 類(lèi)型的數(shù)組當(dāng)做其參數(shù)习勤,而在Java中數(shù)組是一個(gè)對(duì)象踪栋,它是可以泛型化的。所以該例子是不會(huì)產(chǎn)生錯(cuò)誤的图毕。既然例子是將整個(gè)int 類(lèi)型的數(shù)組當(dāng)做泛型參數(shù)夷都,那么經(jīng)過(guò)asList轉(zhuǎn)換就只有一個(gè)int 的列表了.

結(jié)論:

在使用asList()時(shí)盡量不要將基本數(shù)據(jù)類(lèi)型數(shù)組轉(zhuǎn)List.

asList轉(zhuǎn)換得到的ArrayList不是java.util.ArrayList

public static void main(String[] args) {
    String[] arr = {"abc", "kk", "qq"};
    List<String> list = Arrays.asList(arr);
    // 添加一個(gè)元素,拋出異常UnsupportedOperationException
    list.add("bb");
}

原因:

此處ArrayList是Arrays的內(nèi)部類(lèi),并沒(méi)有add方法,add方法是父類(lèi)AbstractList的,但是沒(méi)有具體實(shí)現(xiàn),
而是直接拋出UnsupportedOperationException異常.

Arrays內(nèi)部類(lèi)ArrayList

<figcaption style="line-height: inherit; margin: 0px; padding: 0px; margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;">Arrays內(nèi)部類(lèi)ArrayList</figcaption>

正確操作

public static void main(String[] args) {
    String[] arr = {"abc", "kk", "qq"};
    // 使用new ArrayList包裹一層
    List<String> list = new ArrayList<>(Arrays.asList(arr));
    list.add("bb");
}

如何選用集合?

主要根據(jù)集合的特點(diǎn)來(lái)選用,比如我們需要根據(jù)鍵值獲取到元素值時(shí)就選用Map接口下的集合吴旋,需要排序時(shí)選擇TreeMap,不需要排序時(shí)就選擇HashMap,需要保證線(xiàn)程安全就選用ConcurrentHashMap.當(dāng)我們只需要存放元素值時(shí)损肛,就選擇實(shí)現(xiàn)Collection接口的集合,需要保證元素唯一時(shí)選擇實(shí)現(xiàn)Set接口的集合比如TreeSet或HashSet荣瑟,不需要就選擇實(shí)現(xiàn)List接口的比如ArrayList或LinkedList,然后再根據(jù)實(shí)現(xiàn)這些接口的集合的特點(diǎn)來(lái)選用摩泪。





更多海量學(xué)習(xí)資源與面試指南笆焰,請(qǐng)關(guān)注微信公眾號(hào)【程序論】,免費(fèi)領(lǐng)取见坑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚷掠,一起剝皮案震驚了整個(gè)濱河市捏检,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌不皆,老刑警劉巖贯城,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異霹娄,居然都是意外死亡能犯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)犬耻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)踩晶,“玉大人,你說(shuō)我怎么就攤上這事枕磁《沈撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵计济,是天一觀的道長(zhǎng)茸苇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)沦寂,這世上最難降的妖魔是什么学密? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮凑队,結(jié)果婚禮上则果,老公的妹妹穿的比我還像新娘。我一直安慰自己漩氨,他們只是感情好西壮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著叫惊,像睡著了一般款青。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上霍狰,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天抡草,我揣著相機(jī)與錄音,去河邊找鬼蔗坯。 笑死康震,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宾濒。 我是一名探鬼主播腿短,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了橘忱?” 一聲冷哼從身側(cè)響起赴魁,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钝诚,沒(méi)想到半個(gè)月后颖御,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凝颇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年潘拱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祈噪。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡泽铛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辑鲤,到底是詐尸還是另有隱情盔腔,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布月褥,位于F島的核電站弛随,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宁赤。R本人自食惡果不足惜舀透,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望决左。 院中可真熱鬧愕够,春花似錦、人聲如沸佛猛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)继找。三九已至遂跟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間婴渡,已是汗流浹背幻锁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留边臼,地道東北人哄尔。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像柠并,于是被迫代替她去往敵國(guó)和親究飞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子置谦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353