Java Collections Framework是Java提供的對集合進行定義,操做,和管理的包含一組接口,類的體系結構。html
1. 總體框架java
Java容器類庫一共有兩種主要類型:Collection和Map。層次結構以下: 程序員
藍色橢圓框爲接口類(不可實例化),黑色矩形框爲實現類或子類。面試
Map map = new HashMap(); map.put("key1","lisi1"); map.put("key2","lisi2"); map.put("key3","lisi3"); //Map的keySet()方法先獲取全部鍵的set集合,並經過Set的迭代器進行迭代遍歷 Iterator it = map.keySet().iterator(); while(it.hasNext()){ Object key = it.next(); //經過迭代器遍歷Map的值對象 System.out.println(map.get(key));
}
3.2 Map.entrySet()算法
Set<Map.Entry<K,V>> entrySet(); //把(key-value)做爲一個總體一對一對地存放到Set集合當中的。Map.Entry表示映射關係。entrySet():迭代後能夠e.getKey(),e.getValue()兩種方法來取key和value。返回的是Entry接口。示例:編程
Map map = new HashMap(); map.put("key1","lisi1"); map.put("key2","lisi2"); map.put("key3","lisi3"); //將map集合中的映射關係存入到Set集合,並獲取迭代器用來遍歷 Iterator it = map.entrySet().iterator(); while(it.hasNext()){ //迭代遍歷,並轉類型爲Entry Entry e =(Entry) it.next(); //Entry.getKey ()、Entry.getValue()能夠分別獲得Entry對象的鍵和值 System.out.println("鍵"+e.getKey () + "的值爲" + e.getValue()); }
對比:推薦使用entrySet(),由於效率更高。數組
對於keySet()方法,遍歷了兩次Map,一次用來從HashMap中取出全部key到Set集合,一次從HashMap中取出全部key對應的value。而entrySet()只遍歷了一次,由於直接將key-value做爲總體放入了Entry對象中,因此效率更高。安全
4. 主要實現類對比數據結構
4.1 Vector和ArrayList併發
相同點:都實現了List接口,元素有序可重複;都基於數組的數據結構實現,都容許直接序號索引元素,因此隨機性較好,適合用於查詢,可是增刪移動數據比較慢(用LinkedList);
不一樣點:Vector是線程同步的,因此它也是線程安全的,而ArrayList是線程異步的,是不安全的;Vector因爲使用了synchronized方法(線程安全)因此性能上比ArrayList要差;在集合中使用數據量比較大的數據,用Vector有必定的優點。
4.2ArrayList和LinkedList
相同點:都實現了List接口,元素有序可重複;
不一樣點:具體實現:ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構;效率:對於隨機訪問get和set,ArrayList優於LinkedList,但對於新增和刪除操做add和remove,LinedList比較佔優點。由於LinkedList使用雙向鏈表實現存儲,按序號索引數據須要進行向前或向後遍歷,可是插入數據時只須要記錄本項的先後項便可,而ArrayList每插入一條數據,要移動插入點及以後的全部數據。 這一點要看實際狀況的。若只對單條數據插入或刪除,ArrayList的速度反而優於LinkedList。但如果批量隨機的插入刪除數據,LinkedList的速度大大優於ArrayList。
4.3 HashMap與TreeMap
都實現了Map接口,是一種鍵值對的映射關係。
HashMap經過hashcode對其內容進行快速查找,而TreeMap中全部的元素都保持着某種固定的順序,若是你須要獲得一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。
在Map 中插入、刪除和定位元素,HashMap是最好的選擇。但若是您要按天然順序或自定義順序遍歷鍵,那麼TreeMap會更好。
使用HashMap要求添加的鍵類明肯定義了hashCode()和 equals()的實現。
兩個map中的元素同樣,但順序不同,致使hashCode()不同。
一樣作測試:
在HashMap中,一樣的值的map,順序不一樣,equals時,false;
而在TreeMap中,一樣的值的map,順序不一樣,equals時,true,說明,treeMap在equals()時是整理了順序了的。
4.4 HashTable與HashMap
都實現了Map接口,是一種鍵值對的映射關係。採用的hash/rehash算法相似,性能差別不大。
HashMap不是同步的,是線程不安全的;容許一個null鍵和多個null值。HashTable是同步的,線程安全;不容許有null的鍵或值。
HashTable有contains()方法,在HashMap中只有containsKey()和containsValue()來檢測哈希表中是否有某個key或者value,有則返回true。
一、什麼是Java集合API
Java集合框架API是用來表示和操做集合的統一框架,它包含接口、實現類、以及幫助程序員完成一些編程的算法。簡言之,API在上層完成如下幾件事:編程更加省力,提升城程序速度和代碼質量;非關聯的API提升互操做性;節省學習使用新API成本;節省設計新API的時間;鼓勵、促進軟件重用。
具體來講,有7個集合接口,最基本的是Collection接口,由三個接口Set、List、Queue、SortedSet繼承,另外兩個接口是Map、SortedMap,這兩個接口不繼承Collection,表示映射而不是真正的集合。
二、什麼是Iterator
一些集合類(Set)提供了內容遍歷的功能,經過java.util.Iterator接口。這些接口容許遍歷對象的集合。依次操做每一個元素對象。當使用 Iterators時,在得到Iterator的時候包含一個集合快照。一般在遍歷一個Iterator的時候不建議修改集合本省。
Iterator:只能正向遍歷集合,適用於獲取移除元素。ListIerator:繼承Iterator,能夠雙向列表的遍歷,一樣支持元素的修改。
三、什麼是HaspMap和Map?
Map是接口,Java 集合框架中一部分,用於存儲鍵值對,HashMap是用哈希算法實現Map的類。HashMap是異步的,線程不安全,容許有null鍵值。
HashMap基於hashing原理,咱們經過put(key,value)和get(key)方法儲存和獲取對象。當咱們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,而後找到bucket位置來儲存值對象(HashMap是在bucket中儲存鍵對象和值對象,做爲Map.Entry)。當獲取對象時,經過鍵對象的equals()方法找到正確的鍵值對,而後返回值對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會儲存在鏈表的下一個節點中。 HashMap在每一個鏈表節點中儲存鍵值對對象。
(1)首先equals()和hashcode()這兩個方法都是從object類中繼承過來的。
equals()是對兩個對象的地址值進行的比較(即比較引用是否相同)。
hashCode()是一個本地方法,它的實現是根據本地機器相關的。計算出對象實例的哈希碼,並返回哈希碼,又稱爲散列函數。hashCode()方法的計算依賴於對象實例的D(內存地址),故每一個Object對象的hashCode都是惟一的;固然,當對象所對應的類重寫了hashCode()方法時,結果就大相徑庭了。之因此有hashCode方法,是由於在批量的對象比較中,hashCode要比equals來得快,不少集合都用到了hashCode,好比HashTable。
(2)兩個對象,若是equals()相等,hashCode()必定相等;兩個對象,若是hashCode()相等,equals()不必定相等(Hash散列值有衝突的狀況,雖然機率很低)。
能夠考慮在集合中,判斷兩個對象是否相等的規則是:
第一步,若是hashCode()相等,則查看第二步,不然不相等;
第二步,查看equals()是否相等,若是相等,則兩obj相等,不然仍是不相等。
(3)覆蓋equals()要先覆蓋hashCode(),不然在應用HashMap時會出現各類錯誤。
它們會儲存在同一個bucket位置的鏈表中。鍵對象的equals()方法用來找到鍵值對。
(1)HashMap能夠經過Map map = Collections.synchronizedMap(hashMap)來達到同步的效果。
(詳細的ConcurrentHashMap源碼解析:http://www.importnew.com/22007.html)
四、HashMap與HashTable有什麼區別?對比Hashtable VS HashMap
二者都是用key-value方式獲取數據。Hashtable是原始集合類之一(也稱做遺留類)。HashMap做爲新集合框架的一部分在Java2的1.2版本中加入。它們之間有一下區別:
● HashMap和Hashtable大體是等同的,除了非同步和空值(HashMap容許null值做爲key和value,而Hashtable不能夠)。
● HashMap不是同步的,而Hashtable是同步的。
● 由於線程安全、哈希效率的問題,HashMap效率比HashTable的要高。
● HashTable有contains()方法,在HashMap中只有containsKey()和containsValue()來檢測哈希表中是否有某個key或者value,有則返回true。
● 迭代HashMap採用快速失敗機制,而Hashtable不是,因此這是設計的考慮點。
● HashMap無法保證映射的順序一直不變,可是做爲HashMap的子類LinkedHashMap,若是想要預知的順序迭代(默認按照插入順序),你能夠很輕易的置換爲HashMap,若是使用Hashtable就沒那麼容易了。
HashTable和ConcurrentHashMap都是hash表,都是同步的,不一樣點在於:
HashTable裏使用的是synchronized關鍵字來確保同步,這實際上是對對象加鎖,鎖住的都是對象總體。意味着在一個時間點只能有一個線程能夠修改哈希表,任何線程在執行hashtable的更新操做前須要獲取對象鎖,其餘線程等待鎖的釋放。當Hashtable的大小增長到必定的時候,性能會急劇降低,由於迭代時須要被鎖定很長的時間,效率低下。
ConcurrentHashMap算是對上述問題的優化,它引入了一個「分段鎖」的概念來實現高併發。在ConcurrentHashMap中,就是把HashMap分紅了N(默認爲16)個Segment,諸如get,put,remove等經常使用操做只鎖當前須要用到的桶,根據key.hashCode()算出放到哪一個Segment中。在put的時候須要鎖住該Segment,get時候不加鎖,使用volatile來保證可見性,只有在求size等全局操做時纔可能須要鎖定整個表。
試想,原來只能一個線程進入,如今卻能同時16個寫線程進入(寫線程才須要鎖定,而讀線程幾乎不受限制),併發性的提高是顯而易見的,所以ConcurrentHashMap的效率遠高於HashTable。
基本的不一樣點是Hashtable同步HashMap不是的,因此不管何時有多個線程訪問相同實例的可能時,就應該使用Hashtable,反之使用HashMap。非線程安全的數據結構能帶來更好的性能。若是在未來有一種可能—你須要按順序得到鍵值對的方案時,HashMap是一個很好的選擇,由於有HashMap的一個子類 LinkedHashMap。因此若是你想可預測的按順序迭代(默認按插入的順序),你能夠很方便用LinkedHashMap替換HashMap。反觀要是使用的Hashtable就沒那麼簡單了。同時若是有多個線程訪問HashMap,Collections.synchronizedMap()能夠代替,總的來講HashMap更靈活。
五、什麼叫作快速失敗特性
從高級別層次來講快速失敗是一個系統或軟件對於其故障作出的響應。一個快速失敗系統設計用來即時報告可能會致使失敗的任何故障狀況,它一般用來中止正常的操做而不是嘗試繼續作可能有缺陷的工做。當有問題發生時,快速失敗系統即時可見地發錯錯誤告警。在Java中,快速失敗與iterators有關。若是一個iterator在集合對象上建立了,其它線程欲「結構化」的修改該集合對象,併發修改異常 (ConcurrentModificationException) 拋出。
六、爲何Vector類認爲是廢棄的或者是非官方地不推薦使用?或者說爲何咱們應該一直使用ArrayList而不是Vector
你應該使用ArrayList而不是Vector是由於默認狀況下你是非同步訪問的,Vector同步了每一個方法,你幾乎從不要那樣作,一般有想要同步的是整個操做序列。同步單個的操做也不安全(若是你迭代一個Vector,你仍是要加鎖,以免其它線程在同一時刻改變集合).並且效率更慢。固然一樣有鎖的開銷即便你不須要,這是個很糟糕的方法在默認狀況下同步訪問。你能夠一直使用Collections.sychronizedList來裝飾一個集合。
事實上Vector結合了「可變數組」的集合和同步每一個操做的實現。這是另一個設計上的缺陷。Vector還有些遺留的方法在枚舉和元素獲取的方法,這些方法不一樣於List接口,若是這些方法在代碼中程序員更趨向於想用它。儘管枚舉速度更快,可是他們不能檢查若是集合在迭代的時候修改了,這樣將致使問題。儘管以上諸多緣由,Oracle也從沒宣稱過要廢棄Vector。