集合類java
A. 面試都喜歡問的java集合類
了一些所謂大公司的Java面試問題,發現對於JAVA集合類的使用都比較看重似的,而自己在這方面還真的是所真甚少,抽空也學習學習吧。
java.util包中就包含了一系列重要的集合類,而對於集合類,主要需要掌握的就是它的內部結構,以及遍歷集合的迭代模式。
介面:Collection
所有集合類的根類型,主要的一個介面轎鍵方法:booleanadd(Ojbectc)
雖返回的是boolean,但不是表示添加成功與否,因為Collection規定:一個集合拒絕添加這個元素,無論什麼原因,都必須拋出異常,這個返回值表示的意義是add()執行後,集合的內容是否改了(就是元素有無數量、位置等變化)。類似的addAll,remove,removeAll,remainAll也是一樣的。
用Iterator模式實現遍歷集合
Collection有一個重要的方法:iterator(),返回一個Iterator(迭代子),用於遍歷集合的所有元素。Iterator模式可以把訪問邏輯從不同類的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。
for(Iteratorit=c.iterator();it.hasNext();){...}
不需要維護遍歷集合的「指針」,所有的內部狀態都有Iterator來維護,而這個Iterator由集合類通過工廠方法生成。
每一種集合類返回的Iterator具體類型可能不同,但它們都實現了Iterator介面,因此,我們不需要關心到底是哪種Iterator,它只需要中慶獲得這個Iterator介面即可,這就是介面的好處,面向對象的威力。
要確保遍歷過程順利完成,電腦培訓認為必須保證遍歷過程中不更改集合的內容(Iterator的remove()方閉培巧法除外),所以,確保遍歷可靠的原則是:只在一個線程中使用這個集合,或者在多線程中對遍歷代碼進行同步。
B. 怎樣從java集合類set中取出數據
創建set的iterator方法:
Set<Object> set = new HashSet<Object>();
Iterator<Object> it = set.iterator();
while(it.hasNext())//判斷是否有下一個
it.next()取出元素。
以上早族方法便是從Set集合中取出數據。
(2)集合類java擴展閱讀:
Java中使用Set介面描述一個集合(集合不允許有「重復值」,注意重復的枝睜模概念),集合Set是Collection的子介面,Set不允許其數據元猛緩素重復出現,也就是說在Set中每一個數據元素都是唯一的。Set介面定義的常用方法如下:
1、size() 獲取Set尺寸(即Set包含數據元素的總數)。
2、 add(Object obj) 向Set中添加數據元素obj。
3、remove(Object obj) 從Set中移除數據元素obj。
4 、contains(Object obj) 判斷當前Set中是否包含數據元素obj,如果包含返回true,否則返回false。
5、iterator() 將Set裝入迭代器。
C. 怎麼才能了解JAVA集合類集合類是什麼
數組是集合的一種,是集合的一個子集,你理解了數組就理解了集合.
理解集合類
集合類存放於java.util包中。
集合類存放的都是對象的引用,而非對象本身,出於表達上的便利,我們稱集合中的對象就是指集合中對象的引用(reference)。
集合類型主要有3種:set(集)、list(列表)和map(映射)。
(1)集
集(set)是最簡單的一種集合,它的對象不按特定方式排序,只是簡單的把對象加入集合中,就像往口袋裡放東西。
對集中成員的訪問和操作是通過集中對象的引用進行的,所以集中不能有重復對象。
集也有多種變體,可以實現排序等功能,如TreeSet,它把對象添加到集中的操作將變為按照某種比較規則將其插入到有序的對象序列中。它實現的是SortedSet介面,也就是加入了對象比較的方法。通過對集中的對象迭代,我們可以得到一個升序的對象集合。
(2)列表
列表的主要特徵是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,當然,它與根本沒有順序的集是不同的。
列表在數據結構中分別表現為:數組和向量、鏈表、堆棧、隊列。
關於實現列表的集合類,是我們日常工作中經常用到的,將在後邊的筆記詳細介紹。
(3)映射
映射與集或列表有明顯區別,映射中每個項都是成對的。映射中存儲的每個對象都有一個相關的關鍵字(Key)對象,關鍵字決定了對象在映射中的存儲位置,檢索對象時必須提供相應的關鍵字,就像在字典中查單詞一樣。關鍵字應該是唯一的。
關鍵字本身並不能決定對象的存儲位置,它需要對過一種散列(hashing)技術來處理,產生一個被稱作散列碼(hash code)的整數值,散列碼通常用作一個偏置量,該偏置量是相對於分配給映射的內存區域起始位置的,由此確定關鍵字/對象對的存儲位置。理想情況下,散列處理應該產生給定范圍內均勻分布的值,而且每個關鍵字應得到不同的散列碼。
集合類簡介
java.util中共有13個類可用於管理集合對象,它們支持集、列表或映射等集合,以下是這些類的簡單介紹
集:
HashSet: 使用HashMap的一個集的實現。雖然集定義成無序,但必須存在某種方法能相當高效地找到一個對象。使用一個HashMap對象實現集的存儲和檢索操作是在固定時間內實現的.
TreeSet: 在集中以升序對對象排序的集的實現。這意味著從一個TreeSet對象獲得第一個迭代器將按升序提供對象。TreeSet類使用了一個TreeMap.
列表:
Vector: 實現一個類似數組一樣的表,自動增加容量來容納你所需的元素。使用下標存儲和檢索對象就象在一個標準的數組中一樣。你也可以用一個迭代器從一個Vector中檢索對象。Vector是唯一的同步容器類??當兩個或多個線程同時訪問時也是性能良好的。
Stack: 這個類從Vector派生而來,並且增加了方法實現棧??一種後進先出的存儲結構。
LinkedList: 實現一個鏈表。由這個類定義的鏈表也可以像棧或隊列一樣被使用。
ArrayList: 實現一個數組,它的規模可變並且能像鏈表一樣被訪問。它提供的功能類似Vector類但不同步。
映射:
HashTable: 實現一個映象,所有的鍵必須非空。為了能高效的工作,定義鍵的類必須實現hashcode()方法和equal()方法。這個類是前面java實現的一個繼承,並且通常能在實現映象的其他類中更好的使用。
HashMap: 實現一個映象,允許存儲空對象,而且允許鍵是空(由於鍵必須是唯一的,當然只能有一個)。
WeakHashMap: 實現這樣一個映象:通常如果一個鍵對一個對象而言不再被引用,鍵/對象對將被舍棄。這與HashMap形成對照,映象中的鍵維持鍵/對象對的生命周期,盡管使用映象的程序不再有對鍵的引用,並且因此不能檢索對象。
TreeMap: 實現這樣一個映象,對象是按鍵升序排列的。
Set和List都是由公共介面Collection擴展而來,所以它們都可以使用一個類型為Collection的變數來引用。這就意味著任何列表或集構成的集合都可以用這種方式引用,只有映射類除外(但也不是完全排除在外,因為可以從映射獲得一個列表。)所以說,把一個列表或集傳遞給方法的標准途徑是使用Collection類型的參數
D. 在Java中,什麼是集合類,跟普通類有什麼區別
簡單的說,集合類有list列,set集和map映射 三大類!x0dx0ax0dx0aSet(集):集合中的對象無排列順序,並且沒有重復的對象純嘩敬.x0dx0ax0dx0aList(隊列):集合中的對象按照索引的順序排列,可以有重復做慎的對象。x0dx0ax0dx0aMap(映射):集合中的每一個元素都是一對一對的,包括一個key對象,一個Value對象(一個Key指向一個Value).集合中沒有重復的key對象,但是vaulue對象可以重復.x0dx0a集合類是進蘆局行集合操作的。
E. java集合是什麼
Java集合是什麼:
Java 中的集合類庫可以幫助我們在程序設計中實現傳統的數據結構。
Java的集合類是一個用來存放對象的容器,有以下特點:
1、Java集合只能存放對象。加入添加了一個基本數據類型,會被自動裝箱後存入集合。
2、集合存放的是多個對象的引用,對象本身是在堆內存中的。
3、集合可以存放不同類型,不限數量的數據類型。
集合分三種:1、Set 2 、List 3、Map,下面進行具體介紹。
擴展鏈接:
主要內容:
1)手寫ArrayList
2)手寫單鏈表
3)手寫LinkedList
4)手寫HashMap
5)手寫HashSet
6)最新並發集合類
學習目標:
1. 掌握手寫ArrayList
2. 掌握手寫單鏈表
3. 掌握手寫LinkedList
4. 掌握手寫HashMap
5. 掌握手寫HashSet
6. 理解最新並發集合類底層原理
視頻課程小結:
01_集合提升訓練_手寫ArrayList_get_size_isEmpty_自定義異常
02_集合提升訓練_手寫ArrayList_構造方法_add
03_集合提升訓練_手寫ArrayList_toString_iterator
04_集合提升循環_手寫單鏈表_get
05_集合提升訓練_手寫單鏈表_add_remove_toString
06_集合提升訓練_手寫LinkedList
07_集合提升訓練_手寫LinkedList_添加內存分配圖
08_集合提升訓練_HashMap的原理和代碼准備
09_集合提升訓練_手寫HashMap的put
10_集合提升訓練_手寫HashMap的get_toString
11_集合提升訓練_手寫HashSet
12_集合提升訓練_新一代並發集合類
F. JAVA的集合類型有哪些
集合類型主要有3種:set(集)、list(列表)和map(映射)。
1、List(有序、可重復)
List里存放的對象是有序的,同時也是可以重復的,List關注的是索引,擁有一系列和索引相關的方法,查詢速度快。因為往list集合里插入或刪除數據時,會伴隨著後面數據的移動,所有插入刪除數據速度慢。
2、Set(無序、不能重復)
Set里存放的對象是無序,不能重復的,集合中的對象不按特定的方式排序,只是簡單地把對象加入集合中。
3、Map(鍵值對、鍵唯一、值不唯一)
Map集合中存儲的是鍵值對,鍵不能重復,值可以重復。根據鍵得到值,對map集合遍歷時先得到鍵的set集合,對set集合進行遍歷,得到相應的值。
(6)集合類java擴展閱讀:
JAVA集合類型四種常見輸出方式:
1、Iterator:迭代輸出,是使用最多的輸出方式。
2、ListIterator:是Iterator的子介面,專門用於輸出List中的內盯扒亂容。
3、foreach輸出:JDK1.5之後提供的新功凱檔能,可以輸出數組或集合。
4、for循環。
代碼示例如下此困:
for的形式:for(inti=0;i<arr.size();i++){...}
foreach的形式:for(inti:arr){...}
iterator的形式:
Iterator it = arr.iterator();
while(it.hasNext()){ object o =it.next(); ...}
參考資料來源:網路:java集合類
G. java怎麼集合分類
Set 介面繼承 Collection,但不允許重復,使用自己內部的亂念宴一個排列機制。
List 介面繼承 Collection,允許重復,以元素安插的次序來放置元素,不會重新排列。
Map是以鍵值對存高猜放嘩銀!
現在主要用ArrayList和HashMap!
collection介面下由set,list兩大集合實現,set又有HashSet,TreeSet實現,List又由ArrayList,LinkedList實現;另一Map介面由HashMap,TreeMap實現。
H. Java中最常用的集合類框架
一、HashMap的概述
HashMap可以說是Java中最常用的集合類框架之一,是Java語言中非常典型的數據結構。
HashMap是基於哈希表的Map介面實現的,此實現提供所有可選的映射操作。昌平鎮電腦培訓發現存儲的是對的映射,允許多個null值和一個帶念null鍵。但此類不保證映射的順序,特別是它不保證該順序恆久不變。
除了HashMap是非同步以及允許使用null外,HashMap類與Hashtable大致相同。
此實現假定哈希函數將元素適當地分布在各桶之間,可為基本操作(get和put)提供穩定的性能。迭代collection視圖所需的時間與HashMap實例的「容量」(桶的數量)及其大小(鍵-值映射關系數)成比例。所以,如果迭代性能很重要,則不要將初始容量設置得太高(或將載入因子設置得太低)。
HashMap的實例有兩個參數影響其性能:初始容量和載入因子。容量是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。載入因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了載入因子與當前容量的乘積時,則要對該哈希表進行rehash操作(即重建內部數據結構),從而哈希表將具有大約兩倍的桶數。
通常,默認載入因子(0.75)在時間和空間成本上尋求一種折衷。載入因子過高雖然減少了空間開銷,但同時也增加了查詢成本(在大多數HashMap類的操作中,包括get和put操作,都反映了這一點)。在設置初始容量時應該考慮到映射中所需的條目數及其載入因子,以便最大限度地減少rehash操作次數。如果初始容量大於最大條目數除以載入因子,則不會發生rehash操作。
注意,此實現不是同步的。如果多個線程同時訪問一個HashMap實例,而其中至少一個線程從結構上修改了列表,那麼它必須保持外部同步。這通常是通過同步那些用來封裝列表的對象來實現的。但如果沒有這樣的對象存在,則應該使用{@linkCollections#synchronizedMapCollections.synchronizedMap}來進行「包裝」,該方法最好是在創建時完成,為了避免對映射進行意外的非同步操作。
Mapm=Collections.synchronizedMap(newHashMap(...));
二、構造函數
HashMap提供了三個構造函數:
HashMap():構造一個具有默認初始容量(16)和默認載入因子(0.75)的空HashMap。
HashMap(intinitialCapacity):構造一個帶指定初始容量和默認載入因子(0.75)的空HashMap。
HashMap(intinitialCapacity,floatloadFactor):構造一個帶指定初始容量和載入因子的空HashMap。
這里提到了兩個參數:初始容量,載入因子。這兩個參數是影響HashMap性能的重要參數,其中容量表示哈希表中桶的數量,初始容量是創建哈希表時的容量,載入因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度,它衡量的是一個散列表的空間的使用程度,負載因子越大表示散列表的裝填程散唯度越高沖行培,反之愈小。對於使用鏈表法的散列表來說,查找一個元素的平均時間是O(1+a),因此如果負載因子越大,對空間的利用更充分,然而後果是查找效率的降低;如果負載因子太小,那麼散列表的數據將過於稀疏,對空間造成嚴重浪費。系統默認負載因子為0.75,一般情況下我們是無需修改的。
HashMap是一種支持快速存取的數據結構,要了解它的性能必須要了解它的數據結構。
I. Java集合類框架的基本介面有哪些
在JAVA開發中框架給我們提供了很多方便的介面,但是介面到底是什麼呢?在開發中又起到了什麼作用呢,這就是java課程今天需要了解的!
一.為什麼要使用介面
假如有一個需求:要求實現防盜門的功能。門有」開」和」關」的功能,鎖有」上鎖」和」開鎖」的功能。
分析:首先防盜門是一個門,門有開門和關門的功能,還有一把鎖,鎖有開鎖和上鎖,按照面向對象的編程的思想,我們會將門和鎖都作為一個類而單獨存在,但是,不能讓防盜門繼承自門的同時又繼承自鎖,防盜門不是鎖,不符合繼承中isa的關系,在java中支持單繼承。那麼我們如何來解決這一問題,這時就要用到介面。
二.什麼是介面
在軟體中介面是一種規范和標准,他們可以約束類的行為,坦舉慧是一些方法特徵的集合,但是沒有方法的實現,介面其實上也可以看做是一個特殊的抽象類,但是採用和抽象類完全不同的方法來表示,兩者的設計理念也是不同的,抽象類有利於代碼復用,介面利於代碼的擴展和維護。
三.抽象類和介面的區別:
01抽象類可以提供成員方法的實現細節,而介面中只能存在publicabstract方法;
02.抽象類中的成員變數可以是各種類型的,而介面中的成員變數只能是publicstaticfinal類型的;
03.介面中不能含有靜態代碼塊以及靜態方法,而抽象類可以答扒有靜態代碼塊和靜態方法讓答;
04.一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。
J. java集合類哪個函數可以
java集合裡面的函數
java集合裡面的函數_java集合【1】——— 從集合介面框架說起
百里方欣
原創
關注
0點贊·155人閱讀
(一) java集合分類
之前大概分為三種,Set,List,Map三種,JDK5之後,增加Queue.主要由Collection和Map兩個介面衍生出來,同時Collection介面繼承Iterable介面,所以我們也可以說java裡面的集合類主要是由Iterable和Map兩個介面以及他們的子介面或者其實現類組成。我們可以認為Collection介面定義了單列集合的規范,每次只能存儲一個元素,而Map介面定義了雙列集合的規范,每次能存儲一對元素。
Iterable介面:主要是實現遍歷功能
Collection介面: 允許重復
Set介面:無序,元素不可重復,訪問元素只能通過元素本身來訪問。
List介面:有序且可重復,可以根據元素的索引來訪問集合中的元素。
Queue介面:隊列集合
Map介面:映射關系,簡單理解為鍵值對,Key不可重復,與Collection介面關系不大,只是個別函數使用到。
整個介面框架關系如下(來自網路):
(1) Iterable介面
1. 內部定義的方法
java集合最源頭的介面,實現這個介面的作用主要是集合對象可以通過迭代器去遍歷每一個元素。
源碼如下:
// 返回一個內部元素為T類型的迭代器(JDK1.5隻有這個介面)
Iterator iterator();
// 遍歷內部元素,action意思為動作,指可以對每個元素進行操作(JDK1.8添加)
default void forEach(Consumer super T> action) {}
// 創建並返回一個可分割迭代器(JDK1.8添加),分割的迭代器主要是提供可以並行遍歷元素的迭代器,可以適應現在cpu多核的能力,加快速度。
default Spliterator spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
從上面可以看出,foreach迭代以及可分割迭代,都加了default關鍵字,這個是Java 8 新的關鍵字,以前介面的所有介面,具體子類都必須實現,而對於deafult關鍵字標識的方法,其子類可以不用實現,這也是介面規范發生變化的一點。
下面我們分別展示三個介面的調用:
1.1 iterator方法
public static void iteratorHasNext(){
List list=new ArrayList();
list.add("Jam");
list.add("Jane");
list.add("Sam");
// 返回迭代器
Iterator iterator=list.iterator();
// hashNext可以判斷是否還有元素
while(iterator.hasNext()){
//next()作用是返回當前指針指向的元素,之後將指針移向下個元素
System.out.println(iterator.next());
}
}
當然也可以使用for-each loop方式遍歷
for (String item : list) {
System.out.println(item);
}
但是實際上,這種寫法在class文件中也是會轉成迭代器形式,這只是一個語法糖。class文件如下:
public class IterableTest {
public IterableTest() { }
public static void main(String[] args) {
iteratorHasNext();
}
public static void iteratorHasNext() {
List list = new ArrayList();
list.add("Jam");
list.add("Jane");
list.add("Sam");
Iterator iterator = list.iterator();
Iterator var2 = list.iterator();
while(var2.hasNext()) {
String item = (String)var2.next();
System.out.println(item);
}
}
}
需要注意的一點是,迭代遍歷的時候,如果刪除或者添加元素,都會拋出修改異常,這是由於快速失敗【fast-fail】機制。
public static void iteratorHasNext(){
List list=new ArrayList();
list.add("Jam");
list.add("Jane");
list.add("Sam");
for (String item : list) {
if(item.equals("Jam")){
list.remove(item);
}
System.out.println(item);
}
}
從下面的錯誤我們可以看出,第一個元素是有被列印出來的,也就是remove操作是成功的,只是遍歷到第二個元素的時候,迭代器檢查,發現被改變了,所以拋出了異常。
Jam
Exception in thread "main" java.util.
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at IterableTest.iteratorHasNext(IterableTest.java:15)
at IterableTest.main(IterableTest.java:7)
1.2 forEach方法
其實就是把對每一個元素的操作當成了一個對象傳遞進來,對每一個元素進行處理。
default void forEach(Consumer super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
```java
當然像ArrayList自然也是有自己的實現的,那我們就可以使用這樣的寫法,簡潔優雅。forEach方法在java8中參數是`java.util.function.Consumer`,可以稱為**消費行為**或者說**動作**類型。
```java
list.forEach(x -> System.out.print(x));
同時,我們只要實現Consumer介面,就可以自定義動作,如果不自定義,默認迭代順序是按照元素的順序。
public class ConsumerTest {
public static void main(String[] args) {
List list=new ArrayList();
list.add("Jam");
list.add("Jane");
list.add("Sam");
MyConsumer myConsumer = new MyConsumer();
Iterator it = list.iterator();
list.forEach(myConsumer);
}
static class MyConsumer implements Consumer {
@Override
public void accept(Object t) {
System.out.println("自定義列印:" + t);
}
}
}
輸出的結果:
自定義列印:Jam
自定義列印:Jane
自定義列印:Sam
1.3 spliterator方法
這是一個為了並行遍歷數據元素而設計的迭代方法,返回的是Spliterator,是專門並行遍歷的迭代器。以發揮多核時代的處理器性能,java默認在集合框架中提供了一個默認的Spliterator實現,底層也就是Stream.isParallel()實現的,我們可以看一下源碼:
// stream使用的就是spliterator
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
default Spliterator spliterator() {
return Spliterators.spliterator(this, 0);
}
public static Stream stream(Spliterator spliterator, boolean parallel) {
Objects.requireNonNull(spliterator);
return new ReferencePipeline.Head<>(spliterator,
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
使用的方法如下:
public static void spliterator(){
List list = Arrays.asList("1", "2", "3","4","5","6","7","8","9","10");
// 獲取可迭代器
Spliterator spliterator = list.spliterator();
// 一個一個遍歷
System.out.println("tryAdvance: ");
spliterator.tryAdvance(item->System.out.print(item+" "));
spliterator.tryAdvance(item->System.out.print(item+" "));
System.out.println("\n-------------------------------------------");
// 依次遍歷剩下的
System.out.println("forEachRemaining: ");
spliterator.forEachRemaining(item->System.out.print(item+" "));
System.out.println("\n------------------------------------------");
// spliterator1:0~10
Spliterator spliterator1 = list.spliterator();
// spliterator1:6~10 spliterator2:0~5
Spliterator spliterator2 = spliterator1.trySplit();
// spliterator1:8~10 spliterator3:6~7
Spliterator spliterator3 = spliterator1.trySplit();
System.out.println("spliterator1: ");
spliterator1.forEachRemaining(item->System.out.print(item+" "));
System.out.println("\n------------------------------------------");
System.out.println("spliterator2: ");
spliterator2.forEachRemaining(item->System.out.print(item+" "));
System.out.println("\n------------------------------------------");
System.out.println("spliterator3: ");
spliterator3.forEachRemaining(item->System.out.print(item+" "));
}
tryAdvance() 一個一個元素進行遍歷
forEachRemaining() 順序地分塊遍歷
trySplit()進行分區形成另外的 Spliterator,使用在並行操作中,分出來的是前面一半,就是不斷把前面一部分分出來
結果如下:
tryAdvance:
1 2
-------------------------------------------
forEachRemaining:
3 4 5 6 7 8 9 10
------------------------------------------
spliterator1:
8 9 10
------------------------------------------
spliterator2:
1 2 3 4 5
------------------------------------------
spliterator3:
6 7
還有一些其他的用法在這里就不列舉了,主要是trySplit()之後,可以用於多線程遍歷。理想的時候,可以平均分成兩半,有利於並行計算,但是不是一定平分的。
2. Collection介面 extend Iterable
Collection介面可以算是集合類的一個根介面之一,一般不能夠直接使用,只是定義了一個規范,定義了添加,刪除等管理數據的方法。繼承Collection介面的有List,Set,Queue,不過Queue定義了自己的一些介面,相對來說和其他的差異比較大。
2.1 內部定義的方法
源碼如下:
boolean add(Object o) //添加元素
boolean remove(Object o) //移除元素
boolean addAll(Collection c) //批量添加
boolean removeAll(Collection c) //批量移除
void retainAll(Collection c) // 移除在c中不存在的元素
void clear() //清空集合
int size() //集合大小
boolean isEmpty() //是否為空
boolean contains(Object o) //是否包含在集合中
boolean containsAll(Collection c) //是否包含所有的元素
Iterator iterator() // 獲取迭代器
Object[] toArray() // 轉成數組
default boolean removeIf(Predicate super E> filter) {} // 刪除集合中復合條件的元素,刪除成功返回true
boolean equals(Object o)
int hashCode()
default Spliterator spliterator() {} //獲取可分割迭代器
default Stream stream() {} //獲取流
default Stream parallelStream() {} //獲取並行流
裡面獲取並行流的方法parallelStream(),其實就是通過默認的ForkJoinPool(主要用來使用分治法(Divide-and-Conquer Algorithm)來解決問題),提高多線程任務的速度。我們可以使用ArrayList來演示一下平行處理能力。例如下面的例子,輸出的順序就不一定是1,2,3...,可能是亂序的,這是因為任務會被分成多個小任務,任務執行是沒有特定的順序的。
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
list.parallelStream()
.forEach(out::println);
2.2 繼承Collection的主要介面
graph LR;
Collection -->List-有順序,可重復
List-有順序,可重復 -->LinkedList-使用鏈表實現,線程不安全
List-有順序,可重復 -->ArrayList-數組實現,線程不安全
List-有順序,可重復 -->Vector-數組實現,線程安全
Vector-數組實現,線程安全 -->Stack-堆棧,先進後出
Collection-->Set-不可重復,內部排序
Set-不可重復,內部排序-->HashSet-hash表存儲
HashSet-hash表存儲-->LinkHashSet-鏈表維護插入順序
Set-不可重復,內部排序-->TreeSet-二叉樹實現,排序
Collection-->Queue-隊列,先進先出
2.2.1 List extend Collection
繼承於Collection介面,有順序,取出的順序與存入的順序一致,有索引,可以根據索引獲取數據,允許存儲重復的元素,可以放入為null的元素。
最常見的三個實現類就是ArrayList,Vector,LinkedList,ArrayList和Vector都是內部封裝了對數組的操作,唯一不同的是,Vector是線程安全的,而ArrayList不是,理論上ArrayList操作的效率會比Vector好一些。
裡面是介面定義的方法:
int size(); //獲取大小
boolean isEmpty(); //判斷是否為空
boolean contains(Object o); //是否包含某個元素
Iterator iterator(); //獲取迭代器
Object[] toArray(); // 轉化成為數組(對象)
T[] toArray(T[] a); // 轉化為數組(特定位某個類)
boolean add(E e); //添加
boolean remove(Object o); //移除元素
boolean containsAll(Collection> c); // 是否包含所有的元素
boolean addAll(Collection extends E> c); //批量添加
boolean addAll(int index, Collection extends E> c); //批量添加,指定開始的索引
boolean removeAll(Collection> c); //批量移除
boolean retainAll(Collection> c); //將c中不包含的元素移除
default void replaceAll(UnaryOperator operator) {}//替換
default void sort(Comparator super E> c) {}// 排序
void clear();//清除所有的元素
boolean equals(Object o);//是否相等
int hashCode(); //計算獲取hash值
E get(int index); //通過索引獲取元素
E set(int index, E element);//修改元素
void add(int index, E element);//在指定位置插入元素
E remove(int index);//根據索引移除某個元素
int indexOf(Object o); //根據對象獲取索引
int lastIndexOf(Object o); //獲取對象元素的最後一個元素
ListIterator listIterator(); // 獲取List迭代器
ListIterator listIterator(int index); // 根據索引獲取當前的位置的迭代器
List subList(int fromIndex, int toIndex); //截取某一段數據
default Spliterator spliterator(){} //獲取可切分迭代器
上面的方法都比較簡單,值得一提的是裡面出現了ListIterator,這是一個功能更加強大的迭代器,繼承於Iterator,只能用於List類型的訪問,拓展功能例如:通過調用listIterator()方法獲得一個指向List開頭的ListIterator,也可以調用listIterator(n)獲取一個指定索引為n的元素的ListIterator,這是一個可以雙向移動的迭代器。
操作數組索引的時候需要注意,由於List的實現類底層很多都是數組,所以索引越界會報錯IndexOutOfBoundsException。
說起List的實現子類:
ArrayList:底層存儲結構是數組結構,增加刪除比較慢,查找比較快,是最常用的List集合。線程不安全。
LinkedList:底層是鏈表結構,增加刪除比較快,但是查找比較慢。線程不安全。
Vector:和ArrayList差不多,但是是線程安全的,即同步。
2.2.2 Set extend Collection
Set介面,不允許放入重復的元素,也就是如果相同,則只存儲其中一個。
下面是源碼方法:
int size(); //獲取大小
boolean isEmpty(); //是否為空
boolean contains(Object o); //是否包含某個元素
Iterator iterator(); //獲取迭代器
Object[] toArray(); //轉化成為數組
T[] toArray(T[] a); //轉化為特定類的數組
boolean add(E e); //添加元素
boolean remove(Object o); //移除元素
boolean containsAll(Collection> c); //是否包含所有的元素
boolean addAll(Collection extends E> c); //批量添加
boolean retainAll(Collection> c); //移除所有不存在於c集合中的元素
boolean removeAll(Collection> c); //移除所有在c集合中存在的元素
void clear(); //清空集合
boolean equals(Object o); //是否相等
int hashCode(); //計算hashcode
default Spliterator spliterator() {} //獲取可分割迭代器
主要的子類:
HashSet
允許空值
通過HashCode方法計算獲取hash值,確定存儲位置,無序。
LinkedHashSet
HashSet的子類
有順序
TreeSet
如果無參數構建Set,則需要實現Comparable方法。
亦可以創建時傳入比較方法,用於排序。
2.2.3 Queue extend Collection
隊列介面,在Collection介面的接觸上添加了增刪改查介面定義,一般默認是先進先出,即FIFO,除了優先隊列和棧,優先隊列是自己定義了排序的優先順序,隊列中不允許放入null元素。
下面是源碼:
boolean add(E e); //插入一個元素到隊列,失敗時返回IllegalStateException (如果隊列容量不夠)
boolean offer(E e); //插入一個元素到隊列,失敗時返回false
E remove(); //移除隊列頭的元素並移除
E poll(); //返回並移除隊列的頭部元素,隊列為空時返回null
E element(); //返回隊列頭元素
E peek(); //返回隊列頭部的元素,隊列為空時返回null
主要的子介面以及實現類有:
Deque(介面):Queue的子介面,雙向隊列,可以從兩邊存取
ArrayDeque:Deque的實現類,底層用數組實現,數據存貯在數組中
AbstractQueue:Queue的子介面,僅實現了add、remove和element三個方法
PriorityQueue:按照默認或者自己定義的順序來排序元素,底層使用堆(完全二叉樹)實現,使用動態數組實現,
BlockingQueue: 在java.util.concurrent包中,阻塞隊列,滿足當前無法處理的操作。
(2) Map介面
定義雙列集合的規范Map,每次存儲一對元素,即key和value。
key的類型可以和value的類型相同,也可以不同,任意的引用類型都可以。
key是不允許重復的,但是value是可以重復的,所謂重復是指計算的hash值系統。
下面的源碼的方法:
V put(K key, V value); // 添加元素
V remove(Object key); // 刪除元素
void putAll(Map extends K, ? extends V> m); // 批量添加
void clear() // 移除所有元素
V get(Object key); // 通過key查詢元素
int size(); // 查詢集合大小
boolean isEmpty(); // 集合是否為空
boolean containsKey(Object key); // 是否包含某個key
boolean containsValue(Object value); // 是否包含某個value
Set keySet(); // 獲取所有key的set集合
Collection values(); // 獲取所有的value的set集合
Set> entrySet(); // 返回鍵值對的set,每一個鍵值對是一個entry對象
boolean equals(Object o); // 用於比較的函數
int hashCode(); // 計算hashcode
default V getOrDefault(Object key, V defaultValue) // 獲取key對應的Value,沒有則返回默認值()
default void forEach(BiConsumer super K, ? super V> action) {} // 遍歷
default void replaceAll(BiFunction super K, ? super V, ? extends V> function) {} // 批量替換
// 缺少這個key的時候才會添加進去
// 返回值是是key對應的value值,如果不存在,則返回的是剛剛放進去的value
default V putIfAbsent(K key, V value) {}
default boolean remove(Object key, Object value) {} // 移除元素
default boolean replace(K key, V oldValue, V newValue) {} // 替換
default V replace(K key, V value) {} //替換
// 和putIfAbsent有點像,只不過傳進去的mappingFunction是映射函數,也就是如果不存在key對應的value,將會執行函數,函數返回值會被當成value添加進去,同時返回新的value值
default V computeIfAbsent(K key,Function super K, ? extends V> mappingFunction) {}
// 和computeIfAbsent方法相反,只有key存在的時候,才會執行函數,並且返回
default V computeIfPresent(K key,BiFunction super K, ? super V, ? extends V> remappingFunction) {}
// 不管如何都會執行映射函數,返回value
default V compute(K key,BiFunction super K, ? super V, ? extends V> remappingFunction) {}
default V merge(K key, V value,BiFunction super V, ? super V, ? extends V> remappingFunction) {}
值得注意的是,Map裡面定義了一個Entry類,其實就是定義了一個存儲數據的類型,一個entry就是一個.
Map的常用的實現子類:
HashMap:由數組和鏈表組成,線程不安全,無序。
LinkedHashMap:如果我們需要是有序的,那麼就需要它,時間和空間效率沒有HashMap那麼高,底層是維護一條雙向鏈表,保證了插入的順序。
ConcurrentHashMap:線程安全,1.7JDK使用鎖分離,每一段Segment都有自己的獨立鎖,相對來說效率也比較高。JDK1.8拋棄了Segment,使用Node數組+鏈表和紅黑樹實現,在線程安全控制上使用Synchronize和CAS,可以認為是優化的線程安全的HashMap。
HashTable:對比與HashMap主要是使用關鍵字synchronize,加上同步鎖,線程安全。
(二)總結
這些集合原始介面到底是什麼?為什麼需要?
我想,這些介面其實都是一種規則/規范的定義,如果不這么做也可以,所有的子類自己實現,但是從迭代以及維護的角度來說,這就是一種抽象或者分類,比如定義了Iterator介面,某一些類就可以去繼承或者實現,那就得遵守這個規范/契約。可以有所拓展,每個子類的拓展不一樣,所以每個類就各有所長,但是都有一個中心,就是原始的集合介面。比如實現Map介面的所有類的中心思想都不變,只是各有所長,各分千秋,形成了大千集合世界。
【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。個人寫作方向:Java源碼解析,JDBC,Mybatis,Spring,redis,分布式,劍指Offer,LeetCode等,認真寫好每一篇文章,不喜歡標題黨,不喜歡花里胡哨,大多寫系列文章,不能保證我寫的都完全正確,但是我保證所寫的均經過實踐或者查找資料。遺漏或者錯誤之處,還望指正。
平日時間寶貴,只能使用晚上以及周末時間學習寫作,關注我,我們一起成長吧~