在java
中我們最常的資料介面就是集合,在面試的時候最常問的問題也是集合相關的問題,結合自己的面試經驗,我做了簡單地整理,希望可以能夠幫助小夥伴們一二。
集合有兩個介面組成:Collection
和Map
Collection介面有3個子介面分別是:
List
:有序且元素是可重複的Set
:無序並元素是不可重複的Queue
:先進先出的線性資料結構,並且只能觀察到隊首元素.List介面
List的常用實現類有:
ArrayList
:底層是通過陣列實現的,查詢效能高,插入和刪除比較慢。它遍歷的優勢是在於它在記憶體的連續性決定的。LinkedList
:通過雙向連結串列實現,查詢效能略低,但插入和刪除效能高,除了實現了List
介面,還實現了Queue
介面。Vector
:資料結構與ArrayList
類似,通過synchronized
來實現執行緒安全,並且Stack
棧是實現Vector
介面的。重點知識點:
1.實現ArrayList
執行緒安全的方式
synchronized
或者鎖Vector
,但jdk1.2官方推薦棄用Collections.synchronizedList(list)
來實現2.ArrayList
的構建與擴容
ArrayList arrayList =new ArrayList()
,預設生成一個容量為0的陣列,只有add()
元素時才會分配預設10的初始容量。3.ArrayList
插入和刪除為什麼效能比較差?
插入和刪除都涉及到了陣列的copy
(即資料遷移),操作的位置越在前面,需要copy
的陣列長度就越長。
4.Vector
為什麼會被棄用?
Vector
所有的方法都使用了synchronized
來實現執行緒安全的,這種在所有方法上都使用了synchronized
極大影響了整個資料操作的效能,實際上hashtable
也有類似的問題。所以ArrayList
在jdk1.2後作為Vector
的替代品。
Set介面
Set的常用實現類有:
HashSet
:是基於HashMap
實現的,預設建構函式是構建一個初始容量為16,負載因子為0.75 的HashMap
。通過重寫equals(Object obj)
方法和hashCode()
來實現去重。TreeSet
:資料結構是紅黑樹,通過比較器來實現去重。它的有序性指的是:會通過比較器隊元素進行排序。LinkedHashSet
:LinkedHashSet
底層使用LinkedHashMap
來儲存所有元素,通過重寫equals(Object obj)
方法和 hashCode()
來實現去重。它的有序性指的是,儲存的順序和取出的順序是一致的。Queue介面
Queue的實現類主要有三類:
ConcurrentLinkedQueue
,採用CAS
操作實現無界執行緒安全佇列,避免了加鎖影響了效能。ArrayBlockingQueue
(有界)、LinkedBlockingQueue
(無界),它的阻塞性表現在當佇列滿了,再新增元素時會阻塞該執行緒,暫停新增,等待佇列有空位置。Dueue
,元素可以在兩端進行新增和移除操作。Queue
常見的方法:
add()
:在佇列隊尾新增元素,已滿拋異常。offer()
:在佇列隊尾新增元素,已滿返回false
。remove()
:刪除隊首元素,元素為空拋異常。poll()
:刪除隊首元素,元素為空返回null
,不為空則得到該元素。element()
:查詢隊首元素,為空拋異常。peek()
:查詢隊首元素,為空返回null
。ConcurrentLinkedQueue
ConcurrentLinkedQueue
是java.util.concurrent
下提供的原子操作的執行緒安全佇列,它和LinkedBlockingQueue
都是執行緒安全的,它們的區別在於:
LinkedBlockingQueue
: 多用於任務佇列,適用於一個消費者消費多個不同的生產者不同的訊息。ConcurrentLinkedQueue
:多用於訊息佇列,適用於一個生產者為不同的消費者提供相同的訊息。ArrayBlockingQueue
ArrayBlockingQueue
執行緒池設定經常使用到的有界阻塞佇列。
ArrayList
不適合做佇列,但是陣列是可以做佇列,ArrayBlockingQueue
的實現就是一個環形佇列,它是一個定長的、執行緒安全阻塞式佇列,內部是用一個定長陣列來實現的。它的執行緒安全和阻塞性都是通過ReentrantLock
來實現的。ArrayBlockingQueue
的出佇列和入佇列過程,可以抽象地看作一個在記憶體上定長的遊標卡尺。所以當發生出隊時,隊頭是不斷變化的,並不是一直items[0]
,第一次是0,第二次出隊是1,所以這樣就不需要涉及資料遷移的操作了。 private final E[] items;//底層資料結構
private int takeIndex;//用來為下一個take/poll/remove的索引(出隊)
private int putIndex;//用來為下一個put/offer/add的索引(入隊)
private int count;//佇列中元素的個數
/** Main lock guarding all access */
private final ReentrantLock lock;//鎖
/** Condition for waiting takes */
private final Condition notEmpty;//等待出隊的條件
/** Condition for waiting puts */
private final Condition notFull;//等待入隊的條件
1.集合和陣列的區別
集合和陣列的相互轉變
//array轉換為list
int[] arr = {1,3,4,6,6};
List list =Arrays.asList(arr);
//list轉化成Array
String arratb[] =(String [])list.toArray();
2.集合的種類
ArrayList
。synchronized
同步鎖,嚴重犧牲了效能,而且對並行的效率就 更低了,如HashTable
。ConcurrentLinkedQueue
。3.java提供的集合工具類——Collections
Collections是java
提供的一個 Set
、List
和Map
等集合的工具類, 提供了大量方法對集合進行排序、查詢和修改等操作:
Collections.sort(list)
:使用集合中的某一欄位,對集合進行排序:Collections.shuffle(list)
: 對集合進行隨機排序:Collections.binarySearch(list, "o")
:查詢指定集合中的元素,返回所查詢元素的索引Collections.max(list)/Collections.min(list)
:求最大值/求最小值Collections.indexOfSubList(list, subList)/Collections.lastindexOfSubList(list, subList)
:首次/最後一次 出現元素的索引Collections.replaceAll(list, "a", "b")
:替換批定元素為某元素,若要替換的值存在剛返回true
,反之返回false
Collections.reverse(list)
:反轉集合中元素的順序Collections提供對集合物件實現同步控制等方法:
Collections.synchronizedCollection(collection)
:針對實現collection
介面物件的集合提供執行緒同步控制Collections.synchronizedList(list)
:針對實現list
介面物件的集合提供執行緒同步控制Collections.synchronizedSet(set)
:針對實現set
介面物件的集合提供執行緒同步控制Collections.synchronizedMap(map)
:針對實現map
介面物件的集合提供執行緒同步控制4.流式表示式
Stream 是 Java8
中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。
Stream的特性:
stream
,stream
不會專門儲存資料。stream
的操作也不會影響到建立它的陣列和集合 ,對於stream
的聚合、消費或收集操作(終止操作)只能進行一次,再次操作會報錯。Stream
延遲執行的特性,意味著它在聚合操作執行前修改資料來源是允許的,一旦開始聚合操作就不允許了。聚合操作
聚合操作類似SQL
語句一樣的操作, 比如filter
, map
, reduce
, find
, match
, sorted
等:
中間操作
中間操作返回結果還是Stream
流物件。
篩選與切片
filter
:過濾流中的某些元素limit(n)
:獲取n個元素skip(n)
:跳過n元素,配合limit(n)
可實現分頁distinct()
:通過流中元素的 hashCode()
和 equals()
去除重複元素對映
map()
:接收一個函數作為引數,該函數會被應用到每個元素上,並將其對映成一個新的元素。flatMap()
:接收一個函數作為引數,將流中的每個值都換成另一個流,然後把所有流連線成一個流。排序
sorted()
:產生一個新流,其中按自然順序排序。sorted(Comparator comp)
: 產生一個新流,其中按比較器順序排序終止操作
終止操作與中間操作相比,終止操作返回值已經不再是Stream
流物件了,所以叫終止操作,能夠獲取到對應的值了。
一個是Stream
流物件只能執行一次終止操作。
查詢與匹配
allMatch(Predicate p)
:檢查是否匹配所有元素findAny()
: 返回當前流中的任意元素max(Comparator c)
: 返回流中最大值forEach(Consumer c)
:迭代器歸約
reduce(T iden,BinaryOperator b)
: 可以將流中元素反覆結合起來,得到一個值。reduce(BinaryOperator b)
: 可以將流中元素反覆結合起來,得到一個值。返回Optional
。收集
collect(Collector c)
: 將流轉換為其他形式。接收一個Collector
介面的實現,用於給Stream
中元素