簡(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ì)象。
使用集合框架的好處
- 容量自增長(zhǎng);
- 提供了高性能的數(shù)據(jù)結(jié)構(gòu)和算法历谍,使編碼更輕松现拒,提高了程序速度和質(zhì)量;
- 允許不同 API 之間的互操作望侈,API之間可以來(lái)回傳遞集合印蔬;
- 可以方便地?cái)U(kuò)展或改寫(xiě)集合,提高代碼復(fù)用性和可操作性脱衙。
- 通過(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)
- 允許我們向前蠢正、向后兩個(gè)方向遍歷 List骇笔;
- 在遍歷時(shí)修改 List 的元素;
- 遍歷時(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è)接口派生而出:Collection和Map,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異常.
<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)選用摩泪。