關於集合的體系是每一個人都應該爛熟於心的,尤爲是對咱們常用的List,Map的原理更該如此.這裏咱們看這張圖便可:java
List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不容許有重複元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形。面試
ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增長和插入元素,它們都容許直接按序號索引元素,可是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢。Vector中的方法因爲添加了synchronized修飾,所以Vector是線程安全的容器,但性能上較ArrayList差,所以已是Java中的遺留容器。算法
LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元經過附加的引用關聯起來,造成一個能夠按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據須要進行前向或後向遍歷,可是插入數據時只須要記錄本項的先後項便可,因此插入速度較快。編程
Vector屬於遺留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,可是因爲ArrayList和LinkedListed都是非線程安全的,若是遇到多個線程操做同一個容器的場景,則能夠經過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器後再使用(這是對裝潢模式的應用,將已有對象傳入另外一個類的構造器中建立新的對象來加強實現)。數組
Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操做,這些方法包括對容器的搜索、排序、線程安全化等等。安全
List以特定索引來存取元素,能夠有重複元素。數據結構
Set不能存放重複元素(用對象的equals()方法來區分元素是否重複)。多線程
Map保存鍵值對(key-value pair)映射,映射關係能夠是一對一或多對一。併發
Set和Map容器都有基於哈希存儲和排序樹的兩種實現版本,基於哈希存儲的版本理論存取時間複雜度爲O(1),而基於排序樹版本的實如今插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。框架
Set是最簡單的一種集合。集合中的對象不按特定的方式排序,而且沒有重複對象。
List的特徵是其元素以線性方式存儲,集合中能夠存放重複對象。
PriorityQueue 是一個優先級隊列,保證最高或者最低優先級的的元素老是在隊列頭部,可是 LinkedHashMap 維持的順序是元素插入的順序。當遍歷一個 PriorityQueue 時,沒有任何順序保證,可是 LinkedHashMap 課保證遍歷順序是元素插入的順序。
WeakHashMap 的工做與正常的 HashMap 相似,可是使用弱引用做爲 key,意思就是當 key 對象沒有任何引用時,key/value 將會被回收。
最明顯的區別是 ArrrayList底層的數據結構是數組,支持隨機訪問,而 LinkedList 的底層數據結構是雙向循環鏈表,不支持隨機訪問。使用下標訪問一個元素,ArrayList 的時間複雜度是 O(1),而 LinkedList 是 O(n)。
相對於ArrayList,LinkedList的插入,添加,刪除操做速度更快,由於當元素被添加到集合任意位置的時候,不須要像數組那樣從新計算大小或者是更新索引。
LinkedList比ArrayList更佔內存,由於LinkedList爲每個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
Array能夠容納基本類型和對象,而ArrayList只能容納對象。
Array是指定大小的,而ArrayList大小是固定的
ArrayList和Vector在不少時候都很相似。
如下是ArrayList和Vector的不一樣點。
HashMap和Hashtable都實現了Map接口,所以不少特性很是類似。可是,他們有如下不一樣點:
引入ConcurrentHashMap是爲了在同步集合HashTable之間有更好的選擇,HashTable與HashMap、ConcurrentHashMap主要的區別在於HashMap不是同步的、線程不安全的和不適合應用於多線程併發環境下,而ConcurrentHashMap是線程安全的集合容器,特別是在多線程和併發環境中,一般做爲Map的主要實現。
Comparable 接口用於定義對象的天然順序,而 comparator 一般用於定義用戶定製的順序。Comparable 老是隻有一個,可是能夠有多個 comparator 來定義對象的順序。
poll() 和 remove() 都是從隊列中取出一個元素,可是 poll() 在獲取元素失敗的時候會返回空,可是 remove() 失敗的時候會拋出異常。
private static final int DEFAULT_CAPACITY = 10; //from HashMap.java JDK 7 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
你可使用有序集合,如 TreeSet 或 TreeMap,你也可使用有順序的的集合,如 list,而後經過 Collections.sort() 來排序。
你可使用 Arrays.toString() 和 Arrays.deepToString() 方法來打印數組。因爲數組沒有實現 toString() 方法,因此若是將數組傳遞給 System.out.println() 方法,將沒法打印出數組的內容,可是 Arrays.toString() 能夠打印每一個元素。
雙向循環列表,具體實現自行查閱源碼.
採用紅黑樹實現,具體實現自行查閱源碼.
該問題的關鍵在於面試者使用的是 ArrayList 的 remove() 仍是 Iterator 的 remove()方法。這有一段示例代碼,是使用正確的方式來實如今遍歷的過程當中移除元素,而不會出現 ConcurrentModificationException 異常的示例代碼。
ArrayMap是Android SDK中提供的,非Android開發者能夠略過。
ArrayMap是用兩個數組來模擬map,更少的內存佔用空間,更高的效率。
具體參考這篇文章:ArrayMap VS HashMap:http://lvable.com/?p=217%5D
對於在Map中插入、刪除和定位元素這類操做,HashMap是最好的選擇。然而,假如你須要對一個有序的key集合進行遍歷,TreeMap是更好的選擇。基於你的collection的大小,也許向HashMap中添加元素會更快,將map換爲TreeMap進行有序key的遍歷。
當咱們往Hashmap中put元素時,首先根據key的hashcode從新計算hash值,根絕hash值獲得這個元素在數組中的位置(下標),若是該數組在該位置上已經存放了其餘元素,那麼在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最早加入的放入鏈尾.若是數組中該位置沒有元素,就直接將該元素放到數組的該位置上.
須要注意Jdk 1.8中對HashMap的實現作了優化,當鏈表中的節點數據超過八個以後,該鏈表會轉爲紅黑樹來提升查詢效率,從原來的O(n)到O(logn)
ConcurrentHashMap具體是怎麼實現線程安全的呢,確定不多是每一個方法加synchronized,那樣就變成了HashTable。
從ConcurrentHashMap代碼中能夠看出,它引入了一個「分段鎖」的概念,具體能夠理解爲把一個大的Map拆分紅N個小的HashTable,根據key.hashCode()來決定把key放到哪一個HashTable中。
在ConcurrentHashMap中,就是把Map分紅了N個Segment,put和get的時候,都是現根據key.hashCode()算出放到哪一個Segment中。
Iterator的fail-fast屬性與當前的集合共同起做用,所以它不會受到集合中任何改動的影響。Java.util包中的全部集合類都被設計爲fail->fast的,而java.util.concurrent中的集合類都爲fail-safe的。當檢測到正在遍歷的集合的結構被改變時,Fail-fast迭代器拋出ConcurrentModificationException,而fail-safe迭代器從不拋出ConcurrentModificationException。
這是我在使用 Java 中 Collectionc 類的一些最佳實踐:
Java.util.concurrent.BlockingQueue是一個隊列,在進行檢索或移除一個元素的時候,它會等待隊列變爲非空;當在添加一個元素時,它會等待隊列中的可用空間。BlockingQueue接口是Java集合框架的一部分,主要用於實現生產者-消費者模式。咱們不須要擔憂等待生產者有可用的空間,或消費者有可用的對象,由於它都在BlockingQueue的實現類中被處理了。Java提供了集中BlockingQueue的實現,好比ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue
棧和隊列二者都被用來預存儲數據。java.util.Queue是一個接口,它的實現類在Java併發包中。隊列容許先進先出(FIFO)檢索元素,但並不是老是這樣。Deque接口容許從兩端檢索元素。
棧與隊列很類似,但它容許對元素進行後進先出(LIFO)進行檢索。
Stack是一個擴展自Vector的類,而Queue是一個接口。
本人免費整理了Java高級資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分佈式等教程,一共30G,須要本身領取。
傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q