集合框架使用集合做什么集合的分類具體的實現(xiàn)類ListArrayListLinkedListSetTreeSetMapHashMapTreeMap數(shù)組、List、Set抡驼、Map的數(shù)據(jù)轉(zhuǎn)換數(shù)組轉(zhuǎn) List數(shù)組和Set從Map中得到Set和List散列表(哈希表)的基本原理散列表是如何根據(jù)Key來快速找到它所匹配的 Value 呢 ?散列表的讀寫操作寫操作(put)讀操作(get)IteratorCollections排序查找排序List 集合排序TreeMap 排序自定義類排序外部指定排序本身擁有排序
# 集合框架
程序開發(fā)并不是解決了業(yè)務(wù)的基本功能就完成了,很多時候程序運行的環(huán)境是有限制的。比如內(nèi)存小魔策,CPU頻率低,或者是像手機這樣的設(shè)備河胎,能源供應(yīng)有限闯袒。在這種環(huán)境下,就需要程序能夠在有限的環(huán)境中提升效率游岳。這就需要使用數(shù)據(jù)結(jié)構(gòu)和算法政敢。
但是數(shù)據(jù)結(jié)構(gòu)與算法即便是學(xué)過,也未必在工作時能夠用好胚迫,而且通用性堕仔、性能等等也都是問題。加上學(xué)習(xí)程序開發(fā)的受眾群體越來越廣晌区,讓程序員全部自己實現(xiàn)數(shù)據(jù)結(jié)構(gòu)與算法不是一個好的主意。所以現(xiàn)在很多語言為了能夠提升學(xué)習(xí)效率通贞,降低學(xué)習(xí)門檻朗若,同時也為了讓程序有更好的執(zhí)行效率和通用性,就自帶了各種實現(xiàn)了數(shù)據(jù)結(jié)構(gòu)與算法的API集合昌罩。在Java中哭懈,這就是我們現(xiàn)在要學(xué)習(xí)的「集合框架」
與現(xiàn)在常見到的數(shù)據(jù)結(jié)構(gòu)類庫一樣,Java也是將集合類庫的接口(interface)與實現(xiàn)(implementation)分離茎用。所以我們的學(xué)習(xí)方式一般都是先搞明白接口的分類和關(guān)系遣总,然后根據(jù)不同的接口來學(xué)習(xí)對應(yīng)的實現(xiàn)類睬罗。
## 使用集合做什么
1. 搬運數(shù)據(jù),集合可以存儲數(shù)據(jù)旭斥,然后通過API調(diào)用很方便就可以傳遞大量數(shù)據(jù)
2. 數(shù)據(jù)處理容达,集合中可以直接對數(shù)據(jù)進行操作,比如統(tǒng)計垂券、去重
3. 排序花盐,可以將數(shù)據(jù)按照需求進行各種排序,然后再傳遞給調(diào)用者
## 集合的分類
Java的集合從 Collection 接口和 Map 接口入手
Map 接口和 Collection 沒有交集菇爪,它有自己的方式算芯,只要標準庫后綴不是Map 結(jié)尾的,都是直接或者間接實現(xiàn)了Collection接口凳宙。
Collection 接口中常見的操作是數(shù)據(jù)的添加熙揍、刪除
1. add / addAll
2. remove / removeAll / removeIf
借助 Iterator 接口,Collection 還具備了數(shù)據(jù)的循環(huán)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n429" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public interface Collection<E> extends Iterable<E>{
//...
// 對數(shù)據(jù)循環(huán)
Iterator<E> iterator();
}</pre>
通過 Iterable 接口氏涩, 標準庫中的集合都可以使用 forEach 循環(huán)届囚。
## 具體的實現(xiàn)類
| 集合類型 | 描述 |
| --- | --- |
| ArrayList | 一種可以動態(tài)增長和縮減的索引序列 |
| LinkedList | 一種可以在任何位置進行高效地插人和刪除操作的有序序列 |
| ArrayDeque | 一種用循環(huán)數(shù)組實現(xiàn)的雙端隊列 |
| HashSet | 一種沒有重復(fù)元素的無序集合 |
| TreeSet | 一種有序集 |
| EnumSet | 一種包含枚舉類型值的集 |
| LinkedHashSet | 一種可以記住元素插人次序的集 |
| PriorityQueue | 一種允許高效刪除最小元素的集合 |
| HashMap | 一種存儲鍵/ 值關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu) |
| TreeMap | 一種鍵值有序排列的映射表 |
| EnumMap | 一種鍵值屬于枚舉類型的映射表 |
| LinkedHashMap | 一種可以記住腱/ 值項添加次序的映射表 |
| WeakHashMap | 一種其值無用武之地后可以被垃圾回收器回收的映射表 |
| IdentityHashMap | 一種用 == 而不是用equals 比較鍵值的映射表 |
**Collection**
**Map**
雖然類很多 ,但是我們在教授中只需要交幾個類就可以了削葱,分別是下面:
1. ArrayList
2. LinkedList
3. HashSet
4. HashMap
5. TreeMap
然后加上工具類2個:
1. Collections
2. Arrays
## List
有序集合奖亚,可以精確控制列表中每個元素的插入位置。通過整數(shù)索引獲取列表中的元素析砸。List允許出現(xiàn)重復(fù)的值 昔字, 并可以精確控制列表中每個元素的插入位置,通過整數(shù)索引獲取列表中的元素首繁。
| 方法名 | 說明 |
| --- | --- |
| add(E e) | 增加單個數(shù)據(jù) |
| addAll(Collection<? extends E> c) | 將一個 Collection 集合的數(shù)據(jù)添加到現(xiàn)在的集合中 |
| remove(Object o) | 刪除指定的元素 |
| contains(Object o) | 判斷集合是否包含指定的元素 |
| size() | 得到集合的數(shù)據(jù)總數(shù) |
| isEmpty() | 判斷集合是否有數(shù)據(jù) |
| get(int index) | 通過索引獲取對應(yīng)的數(shù)據(jù)元素 |
| set(int index, E element) | 通過索引和新的元素替換原有內(nèi)容 |
| clear() | 清空數(shù)據(jù) |
| toArray() | 將List轉(zhuǎn)為對象數(shù)組 |
### ArrayList
ArrayList 是List 接口的大小可變數(shù)組的實現(xiàn)作郭。實現(xiàn)了所有可選列表操作, 并允許包括null 在內(nèi)的所有元素弦疮。除了實現(xiàn)List 接口外夹攒, 此類還提供一些方法來操作內(nèi)部用來存儲列表的數(shù)組的大小( 此類大致上等同于 vector 類胁塞, 但 vector 是同步的) 咏尝。
ArrayList 的底層是使用數(shù)組實現(xiàn)的,看下面的圖
可以看到啸罢,數(shù)組中的每一個元素编检,都存儲在內(nèi)存單元中,并且元素之間緊密排列扰才,既不能打亂元素的存儲順序允懂,也不能跳過某個存儲單元進行存儲。
ArrayList 底層既然是使用數(shù)組實現(xiàn)衩匣,那么特點就和數(shù)組一致:**查詢速度快蕾总,增刪速度慢**粥航。
每個ArrayList 實例都有一個容量。該容量是指用來存儲列表元素的數(shù)組的大小生百, 它總是至少等于列表的大小递雀。隨著向Array L ist 中小斷添加元素, 其容量也自動增長置侍。并未指定增長策略的細節(jié)映之,因為這不只是添加元素會帶來分攤固定時間開銷那樣簡單。我們可以使用默認構(gòu)造函數(shù)創(chuàng)建容量為 10 的列表蜡坊, 也可以初始化指定容量大小杠输。
**ArrayList 指定初始容量大小的構(gòu)造器方法**
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n549" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}</pre>
**常用的操作**
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n551" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
// 添加數(shù)據(jù)
list.add(123);
list.add(346);
// 替換數(shù)據(jù)
list.set(1, 777);
// 將list中的所有數(shù)據(jù)放到 list2 中
List<Integer> list2 = new ArrayList<>();
list2.addAll( list );
// 循環(huán)list2中所有的數(shù)據(jù)
for (Integer integer : list2) {
System.out.println( integer );
// 刪除循環(huán)出的對象
list2.remove(integer);
}
// list 集合是否有數(shù)據(jù)
if( !list.isEmpty() ) {
System.out.println("list.size = "+ list.size());
// 清空 list
list.clear();
}
// 在清空list后,再看list現(xiàn)在有多少數(shù)據(jù)
System.out.println("list.size = "+ list.size());
}</pre>
### LinkedList
LinkedList 是一個鏈表結(jié)構(gòu)秕衙,可當(dāng)作堆棧蠢甲、隊列、雙端隊列 据忘。鏈表是一種在物理上非連續(xù)鹦牛、非順序的數(shù)據(jù)結(jié)構(gòu),由若干節(jié)點(node)所組成勇吊。
**單鏈表**
單向鏈表的每一個節(jié)點包含兩部分蔓肯,一部分是存放數(shù)據(jù)的變量data持偏,另一部分是指向下一個節(jié)點的指針next。正如地下黨的聯(lián)絡(luò)方式,一級一級秦躯,單線傳遞:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n558" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private static class Node {
int data;
Node next;
}</pre>
**雙鏈表**
雙向鏈表比單向鏈表稍微復(fù)雜一些涕俗,它的每一個節(jié)點除了擁有data和next指針痰腮,還擁有指向前置節(jié)點的prev指針
和數(shù)組不同赋访,鏈表存儲數(shù)據(jù)的時候,則采用了見縫插針的方式啄枕,鏈表的每一個節(jié)點分布在內(nèi)存的不同位置婚陪,依靠next指針關(guān)聯(lián)起來。這樣可以靈活有效地利用零散的碎片空間频祝。
LinkedList 做**數(shù)據(jù)的添加和刪除操作時速度很快泌参,但是做查詢的時候速度就很慢**,這和 ArrayList 剛好相反常空。
適用 LinkedList 獨有的方法及舍,**在集合前后做數(shù)據(jù)插入**
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n567" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(123);
// 添加相同的數(shù)據(jù)
list.add(123);
list.add(456);
list.add(789);
list.add(101);
// 將數(shù)據(jù) 111 添加到 list 的末尾
list.addLast(111);
// 將數(shù)據(jù) 999 添加到 list的最前面
list.addFirst(999);
for (int i = 0; i < list.size(); i++) {
System.out.println( list.get(i) );
}
}</pre>
> 注意代碼中聲明和實現(xiàn)都是 LinkedList , 如果聲明的是 List 接口 窟绷, addFirst 和 addLast 方法是不可見的
## Set
Set 的特點是去重,如果相同的數(shù)據(jù)只會保留一個咐柜。集合內(nèi)的數(shù)據(jù)是一個無序的狀態(tài)兼蜈,攘残。當(dāng)然也有例外,TreeSet就是有序的为狸。
| 方法名 | 說明 |
| --- | --- |
| add(E e) | 增加單個數(shù)據(jù) |
| addAll(Collection<? extends E> c) | 將一個 Collection 集合的數(shù)據(jù)添加到現(xiàn)在的集合中 |
| remove(Object o) | 刪除指定的元素 |
| contains(Object o) | 判斷集合是否包含指定的元素 |
| size() | 得到集合的數(shù)據(jù)總數(shù) |
| isEmpty() | 判斷集合是否有數(shù)據(jù) |
| clear() | 清空數(shù)據(jù) |
| toArray() | 將List轉(zhuǎn)為對象數(shù)組 |
可以看到歼郭,Set 和 List 中的方法都是相同的,作用也一致辐棒。但是 Set 是沒有直接獲取數(shù)據(jù)的方法病曾。我們更多的時候使用的是 List 和 Map。
Has hSet 由哈希表( 實際上是一個HashM ap 實例) 支持漾根, 為基木操作提供了穩(wěn)定性能泰涂, 這些基本操作包括add() 、remove() 辐怕、contains() 和size() 逼蒙, 假定哈希函數(shù)將這些元素正確地分布在桶中。對此 set() 進行迭代所需的時間與HashSet 實例的大屑氖琛( 元素的數(shù)量) 和底層HashMap 實例( 桶的數(shù)量)的“ 容量” 的和成比例是牢。因此, 如果迭代性能很重要陕截, 則不要將初始容量沒置得太高( 或?qū)⒓虞d因了設(shè)置得太低) 驳棱。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n603" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
HashSet set = new HashSet<>();
set.add( new Object() );
set.add( new Object() );
set.add( "hello" );
set.add( "hello" );
set.add( "你好" );
set.add( 123 );
set.add( 123 );
set.add( 234 );
set.remove("你好");
set.remove( new Object() );
for (Object object : set) {
System.out.println( object );
}
}</pre>
以上代碼經(jīng)輸出可以看到:輸出的內(nèi)容沒有按照輸入時的順序進行輸出。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n605" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">李四
8890
張三
azxcv
ABC</pre>
### TreeSet
Set 集合中的另類农曲,存儲的數(shù)據(jù)時有序的
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n609" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
TreeSet<String> set = new TreeSet<>();
set.add("8890");
set.add("123");
set.add("張三");
set.add("李四");
set.add("ABC");
set.add("azxcv");
for (String string : set) {
System.out.println( string );
}
}</pre>
輸出的結(jié)果:
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="" cid="n611" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">123
8890
ABC
azxcv
張三
李四</pre>
可以發(fā)現(xiàn)數(shù)據(jù)是按照數(shù)字社搅、大寫字母、小寫字母朋蔫、漢字進行排序的罚渐,但是漢字相關(guān)的數(shù)據(jù)本身沒有排序,可以嘗試將李四放在張三的數(shù)據(jù)上面看輸出的結(jié)果驯妄。
## Map
Map 是一種把鍵對象和值對象進行關(guān)聯(lián)的容器荷并, 而一個值對象又可以是一個Map, 依次類推,這樣就可形成一個多級映射青扔。
> 想想學(xué)習(xí)英語使用的詞典軟件源织,輸入英文(key)后,軟件會顯示出對應(yīng)的中文(value)微猖。Map就是在內(nèi)存中的這種結(jié)構(gòu)谈息。
**Key(鍵):**
1. 和 set— 樣,鍵對象不允許重復(fù)凛剥,這是為了保持查找結(jié)果的一致性侠仇。 如果有兩個鍵對象一樣, 那你想得到那個鍵對象所對應(yīng)的值對象時就有問題了。
2. 在使用過程中某個鍵所對應(yīng)的值對象可能會發(fā)生變化逻炊, 這時會按照最后一次修改的值對象與鍵對應(yīng)(就是key同一個key有多次值綁定互亮,最后一個就會覆蓋之前的)
3. 可以使用 null 作為 Key
**Value(值):**
1. 值對象沒有唯一性的要求, 你可以將任意多個鍵都映射到一個值對象上余素, 這不會發(fā)生任何問題( 不過對使用卻可能會造成不便豹休, 你不知道你得到的到底是那一個鍵所對應(yīng)的值對象,所以請不要這樣做)
2. 可以使用 null 作為 Value
> Map 有兩種比較常用的實現(xiàn): HashMap 和 TreeMap
**常用的方法**
| 方法名 | 說明 |
| --- | --- |
| put(key , value) | 儲存數(shù)據(jù) |
| get(key) | 通過key得到值 |
| remove(key) | 通過key刪除對應(yīng)的值(key當(dāng)然也會刪除) |
| entrySet() | 獲取Map所有的Key桨吊,返回一個Set集合 |
| values() | 獲取Map所有的value威根,返回一個List 集合 |
| containsKey(key) | 判斷Map中是否有輸入的參數(shù):key |
| containsValue(value) | 判斷Map中是否有輸入的參數(shù):value |
| size() | 判斷Map中數(shù)據(jù)的總數(shù) |
| clear() | 清空Map中所有的數(shù)據(jù) |
| isEmpty() | 判斷Map中是否有數(shù)據(jù) |
### HashMap
HashMap 用到了哈希碼的算法, 以便快速查找一個鍵视乐。
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n673" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
HashMap<String, String> zsInfo = new HashMap<>();
zsInfo.put("name", "張三");
zsInfo.put("height", "173CM");
zsInfo.put("sex", "男性");
for (Map.Entry<String, String> info : zsInfo.entrySet()) {
System.out.println( info );
}
}</pre>
### TreeMap
TreeMap 是對鍵按序存放洛搀, 因此它便有一些擴展的方法, 比如 firstKey() 炊林、lastKey() 等姥卢, 可以從TreeMap 中指定一個范圍以取得其子Map
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n677" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
TreeMap<String, String> tree = new TreeMap<>();
tree.put("name", "Jack");
tree.put("age", "22");
tree.put("身高", "173");
tree.put("sex", "man");
tree.put("體重", "70KG");
System.out.println("-------------------");
for (Map.Entry<String, String> entry : tree.entrySet()) {
System.out.println( entry );
}
System.out.println("-------------------");
System.out.println("firstKey = "+ tree.firstKey());
System.out.println("firstEntry = "+ tree.firstEntry());
System.out.println("lastKey = "+ tree.lastKey());
System.out.println("lastEntry = "+ tree.lastEntry());
}</pre>
## 數(shù)組、List渣聚、Set独榴、Map的數(shù)據(jù)轉(zhuǎn)換
不同類型的集合相互轉(zhuǎn)換在程序開發(fā)中都是非常常見的 API 操作,這些基礎(chǔ)操作一定要熟悉奕枝。
### 數(shù)組轉(zhuǎn) List
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n683" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">/*
* 數(shù)組轉(zhuǎn)List棺榔,但是這里要注意,Arrays.asList方法轉(zhuǎn)出來的雖然也叫ArrayList隘道,
* 但不是java.util.ArrayList症歇,而是Arrays中的一個內(nèi)部類ArrayList。兩者之間并不相等谭梗。
* 內(nèi)部類ArrayList沒有實現(xiàn)remove忘晤、add等方法,使用的話會報錯激捏。
*/
System.out.println("使用Arrays.asList將數(shù)組轉(zhuǎn)換為List--------------------------------");
String str[] = { "中文", "計算機", "ABC", "123", "qq@qq.com" };
List<String> strList = Arrays.asList(str);
for (String string : strList) {
System.out.println(string);
}
System.out.println("使用ArrayList構(gòu)造器方式再由Arrays.asList將數(shù)組轉(zhuǎn)換為List----------");
// 使用下面的代碼的寫法就不會有問題了设塔。
ArrayList<String> stringsList = new ArrayList<String>(Arrays.asList(str));
// 使用remove方法
stringsList.remove(3);
for (String string : stringsList) {
System.out.println(string);
}
System.out.println("使用List.toArray方法將一個List轉(zhuǎn)換為數(shù)組(默認為Object數(shù)組)----------");
Object[] strArr = stringsList.toArray();
for (Object object : strArr) {
System.out.println(object.toString());
}</pre>
### 數(shù)組和Set
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n685" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">System.out.println("使用Arrays.asList將數(shù)組轉(zhuǎn)換為List--------------------------------");
String str[] = { "中文", "計算機", "ABC", "123", "qq@qq.com" };
System.out.println("下面是數(shù)組轉(zhuǎn)Set ----------------------------------");
Set<String> strSet = new HashSet<String>(Arrays.asList(str));
for (String string : strSet) {
System.out.println(string);
}
System.out.println("下面是將Set集合轉(zhuǎn)換為數(shù)組-------------");
Object[] objArr = strSet.toArray();
for (Object string : objArr) {
System.out.println(string);
}</pre>
### 從Map中得到Set和List
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n687" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Map<String, String> map = new HashMap<String, String>();
map.put("1", "A");
map.put("2", "B");
map.put("3", "C");
// 輸出所有的key , keySet()方法其實返回的就是一個Set集合。
System.out.println("通過keySet輸出所有的key:" + map.keySet());
// 把map的值轉(zhuǎn)為一個List
List<String> stringList = new LinkedList<String>(map.values());
for (String string : stringList) {
System.out.print(string + " ");
}</pre>
## 散列表(哈希表)的基本原理
上面 HashSet 和 HashMap 都使用了 散列表來做數(shù)據(jù)的檢索远舅,那么什么是散列表 闰蛔,這個又有什么優(yōu)點呢 ?
散列表也叫作哈希表(hash table)图柏,這種數(shù)據(jù)結(jié)構(gòu)提供了鍵(Key)和值(Value)的映射關(guān)系序六。只要給出一個Key,就可以高效查找到它所匹配的Value蚤吹,時間復(fù)雜度接近于O(1)例诀。
> 是不是想到了 Map ?
### 散列表是如何根據(jù)Key來快速找到它所匹配的 Value 呢 ?
在目前所學(xué)的數(shù)據(jù)結(jié)構(gòu)中余佃,數(shù)組的查詢效率是最高的暮刃。散列表本質(zhì)就是一個數(shù)組。不同的是**數(shù)組的下標是數(shù)字**爆土,但是**散列表的下標是字符串**。這就需要設(shè)計一個中轉(zhuǎn)站诸蚕,通過某種方式步势,**把Key和數(shù)組下標進行轉(zhuǎn)換。這個中轉(zhuǎn)站就叫作哈希函數(shù)**背犯。
在不同的語言中坏瘩,哈希函數(shù)的實現(xiàn)是不一樣的。我們以Java的HashMap為例漠魏,來看看哈希函數(shù)的實現(xiàn)倔矾。
在Java及大多數(shù)面向?qū)ο蟮恼Z言中,每一個對象都有屬于自己的hashcode柱锹,這個hashcode是區(qū)分不同對象的重要標識哪自。無論對象自身的類型是什么,它們的hashcode都是一個整型變量禁熏。
既然都是整型變量壤巷,想要轉(zhuǎn)化成數(shù)組的下標也就不難實現(xiàn)了。最簡單的轉(zhuǎn)化方式是什么呢瞧毙?是按照數(shù)組長度進行取模運算
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n700" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">index = HashCode (Key) % Array.length</pre>
> 其實JDK中的哈希函數(shù)為了提升效率胧华,使用的是位運算。我們就假設(shè)使用的是模運算
通過哈希函數(shù)宙彪,我們可以把字符串或其他類型的Key矩动,轉(zhuǎn)化成數(shù)組的下標index。如給出一個長度為8的數(shù)組释漆,則當(dāng) key=001121時
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n704" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">index = HashCode ("001121") % Array.length = 1420036703 % 8 = 7</pre>
而當(dāng)key=this時悲没,
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n706" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">index = HashCode ("this") % Array.length = 3559070 % 8 = 6</pre>
### 散列表的讀寫操作
有了哈希函數(shù),就可以在散列表中進行讀寫操作了灵汪。
#### 寫操作(put)
寫操作就是在散列表中插入新的鍵值對(在JDK中叫作Entry)檀训。如調(diào)用hashMap.put("002931", "王五"),意思是插入一組Key為002931享言、Value為王五的鍵值對峻凫。具體該怎么做呢?
1. 通過哈希函數(shù)览露,把Key轉(zhuǎn)化成數(shù)組下標5荧琼。
2. 如果數(shù)組下標5對應(yīng)的位置沒有元素,就把這個Entry填充到數(shù)組下標5的位置
由于數(shù)組的長度是有限的,當(dāng)插入的Entry越來越多時命锄,不同的Key通過哈希函數(shù)獲得的下標有可能是相同的堰乔。例如002936這個Key對應(yīng)的數(shù)組下標是2;002947這個Key對應(yīng)的數(shù)組下標也是2脐恩。
**這種情況镐侯,就叫作哈希沖突**
解決哈希沖突的方法主要有兩種,一種是開放尋址法驶冒,一種是鏈表法
1. 開放尋址法的原理很簡單苟翻,當(dāng)一個Key通過哈希函數(shù)獲得對應(yīng)的數(shù)組下標已被占用時,我們可以“另謀高就”骗污,尋找下一個空檔位置
2. HashMap數(shù)組的每一個元素不僅是一個Entry對象崇猫,還是一個鏈表的頭節(jié)點。每一個Entry對象通過next指針指向它的下一個Entry節(jié)點需忿。當(dāng)新來的Entry映射到與之沖突的數(shù)組位置時诅炉,只需要插入到對應(yīng)的鏈表中即可
#### 讀操作(get)
讀操作就是通過給定的Key,在散列表中查找對應(yīng)的Value屋厘。例如調(diào)用 hashMap.get("002936")涕烧,意思是查找Key為002936的Entry在散列表中所對應(yīng)的值
1. 通過哈希函數(shù),把Key轉(zhuǎn)化成數(shù)組下標2擅这。
2. 找到數(shù)組下標2所對應(yīng)的元素澈魄,如果這個元素的Key是002936,那么就找到了仲翎;如果這個Key不是002936也沒關(guān)系痹扇,由于數(shù)組的每個元素都與一個鏈表對應(yīng),我們可以順著鏈表慢慢往下找溯香,看看能否找到與Key相匹配的節(jié)點鲫构。
## Iterator
iterator是為了實現(xiàn)對Java容器(collection)進行遍歷功能的一個接口。 在iterator實現(xiàn)了Iterator接口后玫坛,相當(dāng)于把一個Collection容器的所有對象结笨,做成一個線性表(List),而iterator本身是一個指針湿镀,開始時位于第一個元素之前炕吸。
| 方法 | 說明 |
| --- | --- |
| hasNext() | 判斷 iterator 內(nèi)是否存在下1個元素,如果存在勉痴,返回true赫模,否則返回false。(注意蒸矛,這時上面的那個指針位置不變) |
| next() | 返回 iterator 內(nèi)下1個元素瀑罗,同時上面的指針向后移動一位胸嘴。如果不斷地循環(huán)執(zhí)行next()方法,就可以遍歷容器內(nèi)所有的元素了 |
| remove() | 刪除 iterator 內(nèi)指針的前1個元素斩祭,前提是至少執(zhí)行過1次next() |
遍歷1個ArrayList 和Linklist是十分容易的劣像,遍歷1個Tree容器也不難,但是實現(xiàn)機制是完全不同摧玫,而遍歷1個Set容器就無從下手了耳奕。 Iterator 這個接口讓各種容器自己去重寫里面的hasNext()和next()方法。 不用關(guān)心各種容器的遍歷機制诬像,只要使用Iterator吮铭,會讓人覺得各種容器的遍歷方法都是一樣的,這就是Java接口的重要意義颅停。
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n753" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">HashMap zsInfo = new HashMap<>();
zsInfo.put("name", "張三");
zsInfo.put("height", "173CM");
zsInfo.put("sex", "男性");
zsInfo.put("skin-color", "白色");
zsInfo.put("height", "183CM");
zsInfo.remove("skin-color");
System.out.println("Iterator 循環(huán)------------------");
Iterator iterator = zsInfo.entrySet().iterator();
while( iterator.hasNext() ) {
Map.Entry next = (Entry) iterator.next();
System.out.println( next );
}</pre>
## Collections
Collections 是 Java 提供對Set 、List 和Map 等集合操作的工具類掠拳。
該工具類里提供了大量方法癞揉,除了對集合元素進行排序、查詢和修改等操作溺欧;還提供了將集合對象設(shè)置為不可變喊熟、對集合對象實現(xiàn)同步控制等方法。
### 排序
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n760" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">ArrayList nums = new ArrayList<>();
nums.add(2);
nums.add(0);
nums.add(-5);
nums.add(0);
nums.add(3);
System.out.println( nums );
Collections.reverse( nums );
System.out.println( nums);
Collections.sort( nums );
System.out.println( nums );
Collections.shuffle( nums );
System.out.println( nums );</pre>
### 查找
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n762" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">ArrayList nums = new ArrayList<>();
nums.add(2);
nums.add(0);
nums.add(-5);
nums.add(0);
nums.add(3);
System.out.println( nums );
System.out.println( Collections.max( nums ));
System.out.println( Collections.min( nums ));
Collections.replaceAll(nums, 0 , 1);
System.out.println( nums );
System.out.println( Collections.frequency(nums, 1));
Collections.sort(nums);
System.out.println( nums );
System.out.println( Collections.binarySearch(nums, 3 ));</pre>
## 排序
集合的排序有2種方式:
1. 集合內(nèi)部就擁有排序的能力姐刁。
需要排序的能力的類實現(xiàn) Comparable 接口的方法
2. 集合本身沒有排序的能力芥牌,可以通過外部指定排序的方式。
在排序方法中聂使,指定一個實現(xiàn)了 Comparator 接口的類的對象
Comparable是需要比較的對象來實現(xiàn)接口壁拉。這樣對象調(diào)用實現(xiàn)的方法來比較。對對象的耦合度高(需要改變對象的內(nèi)部結(jié)構(gòu)柏靶,破壞性大)弃理。
Comparator相當(dāng)于一通用的比較工具類接口。需要定制一個比較類去實現(xiàn)它屎蜓,重寫里面的compare方法痘昌,方法的參數(shù)即是需要比較的對象。對象不用做任何改變炬转,解耦辆苔。
### List 集合排序
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n776" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">List<Integer> list = new ArrayList<Integer>();
list.add(123);
list.add(999);
list.add(101);
list.add(33);
list.add(76);
Collections.sort(list);
for (Integer integer : list) {
System.out.println( integer );
}</pre>
直接就可以得到自然升序,我們在上面的代碼中沒有看到任何接口扼劈,原因是List集合中的 Integer 類本身就實現(xiàn)了 Comparable 接口
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n778" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public final class Integer extends Number implements Comparable<Integer> {
//...
}</pre>
### TreeMap 排序
treeMap 的示例中驻啤,我們使用了外部指定排序方式:Comparator
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n782" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">TreeMap<String, String> tree = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1) ; //
}
});
tree.put("name", "Jack");
tree.put("age", "22");
tree.put("身高", "173");
tree.put("sex", "man");
tree.put("體重", "70KG");
System.out.println("-------------------");
for (Map.Entry<String, String> entry : tree.entrySet()) {
System.out.println( entry );
}</pre>
### 自定義類排序
當(dāng)我們自定義了一個類,也希望能夠進行排序的話测僵,就需要實現(xiàn) Comparator接口或者是 Comparable 接口了街佑。
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n786" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class User {
private Integer uid;
private String uname;
//....
}</pre>
#### 外部指定排序
User 類沒有實現(xiàn) Comparable 接口谢翎,通過 Collections 工具類的 sort 方法進行排序,在 sort 方法的第二個參數(shù)上指定排序的規(guī)則
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n789" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">List<User> list = new ArrayList<User>();
list.add( new User(110 ,"Mark") );
list.add( new User(101 ,"李四") );
list.add( new User(100 ,"張三") );
list.add( new User(111 ,"Jack") );
// Comparator 接口因為是外部排序沐旨,所以需要知道對比的2個對象
Collections.sort(list , new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o2.getUid() - o1.getUid() ;
}
});
for (User user : list) {
System.out.println( user );
}</pre>
#### 本身擁有排序
因為是內(nèi)部排序森逮,所以只需要傳入被排序的對象即可,另一個排序?qū)ο螽?dāng)然是對象本身磁携,使用 this 指向即可褒侧。
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n793" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class User implements Comparable<User> {
private Integer uid;
private String uname;
public User(int i, String string) {
this.uid = i;
this.uname = string;
}
@Override
public int compareTo(User o) {
return this.getUid() - o.getUid() ;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
@Override
public String toString() {
return "User [uid=" + uid + ", uname=" + uname + "]";
}
}
</pre>
排序
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n795" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">List<User> list = new ArrayList<User>();
list.add( new User(110 ,"Mark") );
list.add( new User(101 ,"李四") );
list.add( new User(100 ,"張三") );
list.add( new User(111 ,"Jack") );
Collections.sort(list);
for (User user : list) {
System.out.println( user );
}</pre>
輸出結(jié)果
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="" cid="n797" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">User [uid=100, uname=張三]
User [uid=101, uname=李四]
User [uid=110, uname=Mark]
User [uid=111, uname=Jack]</pre>
2021-05-07 集合框架
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啄寡,“玉大人豪硅,你說我怎么就攤上這事⊥ξ铮” “怎么了懒浮?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長识藤。 經(jīng)常有香客問我砚著,道長,這世上最難降的妖魔是什么蹋岩? 我笑而不...
- 正文 為了忘掉前任赖草,我火速辦了婚禮,結(jié)果婚禮上剪个,老公的妹妹穿的比我還像新娘秧骑。我一直安慰自己,他們只是感情好扣囊,可當(dāng)我...
- 文/花漫 我一把揭開白布乎折。 她就那樣靜靜地躺著,像睡著了一般侵歇。 火紅的嫁衣襯著肌膚如雪攒巍。 梳的紋絲不亂的頭發(fā)上产阱,一...
- 文/蒼蘭香墨 我猛地睜開眼私痹,長吁一口氣:“原來是場噩夢啊……” “哼脐嫂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起紊遵,我...
- 正文 年R本政府宣布捂人,位于F島的核電站御雕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滥搭。R本人自食惡果不足惜酸纲,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瑟匆。 院中可真熱鬧闽坡,春花似錦、人聲如沸愁溜。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽冕象。三九已至代承,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渐扮,已是汗流浹背论悴。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- 未來的13天,是孵化我們自己這顆種子的好時光捐寥,曬太陽笤昨,吹吹風(fēng),多喝水握恳,躺大地瞒窒,有練習(xí)的多做練習(xí),脖子喉輪一帶是關(guān)鍵...