一、集合的由來
通常,我們的程序需要根據程序運行時才知道創建多少個對象。但若非程序運行,程序開發階段,我們根本不知道到底需要多少個數量的對象,甚至不知道它的準確類型。爲了滿足這些常規的編程需要,我們要求能在任何時候,任何地點創建任意數量的對象,而這些對象用什麼來容納呢?我們首先想到了數組,但是數組只能放統一類型的數據,而且其長度是固定的,那怎麼辦呢?集合便應運而生了!
二、集合是什麼?
Java集合類存放於 java.util 包中,是一個用來存放對象的容器。
注意:①、集合只能存放對象。比如你存一個 int 型數據 1放入集合中,其實它是自動轉換成 Integer 類後存入的,Java中每一種基本類型都有對應的引用類型。
②、集合存放的是多個對象的引用,對象本身還是放在堆內存中。
③、集合可以存放不同類型,不限數量的數據類型。
三、Java 集合框架圖
此圖來源於:http://blog.csdn.net/u010887744/article/details/50575735
大圖可以點此訪問:https://img-blog.csdn.net/20160124221843905
三、下面整理的一份集合思維導圖,主要介紹了一下大家平常用到的。
四、下面是思維導圖的文字版本。
集合
List
LinkedList
非線程安全
刪除,插入效率快
查詢時間複雜度O(n)
非線程安全
非線程安全
查找快時間複雜度O(1)
Vector
線程安全
Set
Set裏存放的對象是無序,不能重複的,集合中的對象不按特定的方式排序,只是簡單地把對象加入集合中。
TreeMap
基於 TreeMap 的 NavigableSet 實現。使用元素的自然順序對元素進行排序,或者根據創建 set 時提供的 Comparator進行排序,具體取決於使用的構造方法。
HashSet
HashSet是基於HashMap來實現的,操作很簡單,更像是對HashMap做了一次“封裝”,而且只使用了HashMap的key來實現各種特性,而HashMap的value始終都是PRESENT。
HashSet
HashSet不允許重複(HashMap的key不允許重複,如果出現重複就覆蓋),允許null值,非線程安全。
LinkedHashSet
Map
線程不安全
HashMap
哈希表(hash table)也叫散列表,是一種非常重要的數據結構,應用場景及其豐富,許多緩存技術(比如memcached)的核心其實就是在內存中維護一張大的哈希表
哈希表
數組:採用一段連續的存儲單元來存儲數據。對於指定下標的查找,時間複雜度爲O(1);通過給定值進行查找,需要遍歷數組,逐一比對給定關鍵字和數組元素,時間複雜度爲O(n),當然,對於有序數組,則可採用二分查找,插值查找,斐波那契查找等方式,可將查找複雜度提高爲O(logn);對於一般的插入刪除操作,涉及到數組元素的移動,其平均複雜度也爲O(n)
線性鏈表:對於鏈表的新增,刪除等操作(在找到指定操作位置後),僅需處理結點間的引用即可,時間複雜度爲O(1),而查找操作需要遍歷鏈表逐一進行比對,複雜度爲O(n)
二叉樹:對一棵相對平衡的有序二叉樹,對其進行插入,查找,刪除等操作,平均複雜度均爲O(logn)。
哈希表:相比上述幾種數據結構,在哈希表中進行添加,刪除,查找等操作,性能十分之高,不考慮哈希衝突的情況下,僅需一次定位即可完成,時間複雜度爲O(1),接下來我們就來看看哈希表是如何實現達到驚豔的常數階O(1)的。數組+鏈表;
哈希表主幹是數組,利用鏈表進行解決哈希衝突,JDK1.8之後還會出現紅黑樹。
實現原理
HashMap的主幹是一個Entry數組。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對。
TreeMap
基於紅黑二叉樹的NavigableMap的實現,線程非安全,不允許null,key不可以重複,value允許重複,存入TreeMap的元素應當實現Comparable接口或者實現Comparator接口,會按照排序後的順序迭代元素,兩個相比較的key不得拋出classCastException。主要用於存入元素的時候對元素進行自動排序,迭代輸出的時候就按排序順序輸出
線程安全
HashTable
直接採用Synchronized上鎖
HashTable的get/put方法都被synchronized關鍵字修飾,說明它們是方法級別阻塞的,它們佔用共享資源鎖,所以導致同時只能一個線程操作get或者put,而且get/put操作不能同時執行,所以這種同步的集合效率非常低,一般不建議使用這個集合。
ConcurrentHashMap
分段上鎖 segment
這個也是最推薦使用的線程安全的Map,也是實現方式最複雜的一個集合,每個版本的實現方式也不一樣,在jdk8之前是使用分段加鎖的一個方式,分成16個桶,每次只加鎖其中一個桶,而在jdk8又加入了紅黑樹和CAS算法來實現。
SynchronizedMap
private Map<String, Object> map = Collections.synchronizedMap(new HashMap<String, Object>()); 這種是直接使用工具類裏面的方法創建SynchronizedMap,把傳入進行的HashMap對象進行了包裝同步。
加的對象鎖,同樣效率也是很低,不建議使用。