Collection集合框架集
java培訓之Collection集合框架集
Map

Map概述
- Map與Collection并列存在。用于保存具有映射關(guān)系的數(shù)據(jù):Key-Value
- Map 中的 key 和 value 都可以是任何引用類型的數(shù)據(jù)
- Map 中的 key 不允許重復
- key 和 value 之間存在單向一對一關(guān)系,即通過指定的 key 總能找到唯一的、確定的 value。
- Map接口的常用實現(xiàn)類:HashMap、TreeMap、linkedHashMap和Properties。
- HashMap是 Map 接口使用頻率最高的實現(xiàn)類。
- 允許使用null鍵和null值,與HashSet一樣,不保證映射的順序。
Map的常用方法:
1、添加、刪除操作:
- Object put(Object key,Object value)
- Object remove(Object key)
- void putAll(Map t)
- void clear()
2、元素查詢的操作:
- Object get(Object key)
- boolean containsKey(Object key)
- boolean containsValue(Object value)
- int size()
- boolean isEmpty()
3、元視圖操作的方法:
- Set keySet()
- Collection values()
- Set entrySet()
Map的遍歷
Collection集合的遍歷:(1)foreach(2)通過Iterator對象遍歷
Map的遍歷,不能支持foreach
(1)分開遍歷:單獨遍歷所有key,還可以根據(jù)key獲取對應(yīng)value
單獨遍歷所有value
(2)成對遍歷:遍歷的是映射關(guān)系Map.Entry
Map.Entry是Map接口的內(nèi)部接口。每一種Map內(nèi)部有自己的Map.Entry的實現(xiàn)類
在Map中存儲數(shù)據(jù),實際上是將Key—->value的數(shù)據(jù)存儲在Map.Entry接口的實例中,再在Map集合中插入Map.Entry的實例化對象,如圖示:
public static void main(String[] args) {
Map map = new HashMap();
map.put(“邢濤”, 60);
map.put(“林明明”, 70);
map.put(“田杰”, 80);
map.put(“李鎧”, 90);
map.put(“李信”, 60);
System.out.println(“map的所有key:”);
Set keys = map.keySet();//HashSet
for(Object key : keys){
System.out.println(key+”->”+map.get(key));
}
System.out.println(“map的所有的value:”);
Collection values = map.values();
Iterator iter = values.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
System.out.println(“map所有的映射關(guān)系:”);
//映射關(guān)系的類型是Map.Entry類型,它是Map接口的內(nèi)部接口
Set mappings = map.entrySet();
for(Object mapping : mappings){
//System.out.println(mapping);
Map.Entry entry = (Map.Entry)mapping;
System.out.println(“key是:”+ entry.getKey()+ “,value是:”+entry.getValue());
}
}
Map的實現(xiàn)類
1、HashMap
HashMap 判斷兩個 key 相等的標準是:兩個 key 通過 equals() 方法返回 true,hashCode 值也相等。
HashMap 判斷兩個 value相等的標準是:兩個 value 通過 equals() 方法返回 true。
HashMap線程不安全
JDK1.8之前:
HashMap的內(nèi)部存儲結(jié)構(gòu)其實是數(shù)組和鏈表的結(jié)合。當實例化一個HashMap時,系統(tǒng)會創(chuàng)建一個長度為Capacity的Entry數(shù)組,這個長度在哈希表中被稱為容量(Capacity),在這個數(shù)組中可以存放元素的位置我們稱之為“桶”(bucket),每個bucket都有自己的索引,系統(tǒng)可以根據(jù)索引快速的查找bucket中的元素。
每個bucket中存儲一個元素,即一個Entry對象,但每一個Entry對象可以帶一個引用變量,用于指向下一個元素,因此,在一個桶中,就有可能生成一個Entry鏈。而且新添加的元素作為鏈表的head。
HashMap的擴容
當HashMap中的元素越來越多的時候,hash沖突的幾率也就越來越高,因為數(shù)組的長度是固定的。所以為了提高查詢的效率,就要對HashMap的數(shù)組進行擴容,而在HashMap數(shù)組擴容之后,最消耗性能的點就出現(xiàn)了:原數(shù)組中的數(shù)據(jù)必須重新計算其在新數(shù)組中的位置,并放進去,這就是resize。
那么HashMap什么時候進行擴容呢?
當HashMap中的元素個數(shù)超過數(shù)組大小(數(shù)組總大小length,不是數(shù)組中個數(shù)size)*loadFactor時,就會進行數(shù)組擴容,loadFactor的默認值為0.75,這是一個折中的取值。也就是說,默認情況下,數(shù)組大小為16,那么當HashMap中元素個數(shù)超過16*0.75=12(這個值就是代碼中的threshold值,也叫做臨界值)的時候,就把數(shù)組的大小擴展為 2*16=32,即擴大一倍,然后重新計算每個元素在數(shù)組中的位置,而這是一個非常消耗性能的操作,所以如果我們已經(jīng)預(yù)知HashMap中元素的個數(shù),那么預(yù)設(shè)元素的個數(shù)能夠有效的提高HashMap的性能。
JDK1.8之后:
HashMap的內(nèi)部存儲結(jié)構(gòu)其實是數(shù)組和鏈表/樹的結(jié)合。當實例化一個HashMap時,會初始化initialCapacity和loadFactor,在put第一對映射關(guān)系時,系統(tǒng)會創(chuàng)建一個長度為initialCapacity的Node數(shù)組,這個長度在哈希表中被稱為容量(Capacity),在這個數(shù)組中可以存放元素的位置我們稱之為“桶”(bucket),每個bucket都有自己的索引,系統(tǒng)可以根據(jù)索引快速的查找bucket中的元素。
每個bucket中存儲一個元素,即一個Node對象,但每一個Node對象可以帶一個引用變量next,用于指向下一個元素,因此,在一個桶中,就有可能生成一個Node鏈。也可能是一個一個TreeNode對象,每一個TreeNode對象可以有兩個葉子結(jié)點left和right,因此,在一個桶中,就有可能生成一個TreeNode樹。而新添加的元素作為鏈表的last,或樹的葉子結(jié)點。(七上八下)
那么HashMap什么時候進行擴容和樹形化呢?
當HashMap中的元素個數(shù)超過數(shù)組大小(數(shù)組總大小length,不是數(shù)組中個數(shù)size)*loadFactor時,就會進行數(shù)組擴容,loadFactor的默認值為0.75,這是一個折中的取值。也就是說,默認情況下,數(shù)組大小為16,那么當HashMap中元素個數(shù)超過16*0.75=12(這個值就是代碼中的threshold值,也叫做臨界值)的時候,就把數(shù)組的大小擴展為 2*16=32,即擴大一倍,然后重新計算每個元素在數(shù)組中的位置,而這是一個非常消耗性能的操作,所以如果我們已經(jīng)預(yù)知HashMap中元素的個數(shù),那么預(yù)設(shè)元素的個數(shù)能夠有效的提高HashMap的性能。
當HashMap中的其中一個鏈的對象個數(shù)如果達到了8個,此時如果capacity沒有達到64,那么HashMap會先擴容解決,如果已經(jīng)達到了64,那么這個鏈會變成樹,結(jié)點類型由Node變成TreeNode類型。當然,如果當映射關(guān)系被移除后,下次resize方法時判斷樹的結(jié)點個數(shù)低于6個,也會把樹在轉(zhuǎn)為鏈表。
關(guān)于映射關(guān)系的key是否可以修改?
映射關(guān)系存儲到HashMap中會存儲key的hash值,這樣就不用在每次查找時重新計算每一個Entry或Node(TreeNode)的hash值了,因此如果已經(jīng)put到Map中的映射關(guān)系,再修改key的屬性,而這個屬性又參與hashcode值的計算,那么會導致匹配不上。
HashSet的底層實現(xiàn)
public class HashSet<E> ……{
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
public Iterator<E> iterator() {
return map.keySet().iterator();
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public void clear() {
map.clear();
}
}
2、linkedHashMap
linkedHashMap 是 HashMap 的子類
與linkedHashSet類似,linkedHashMap 可以維護 Map 的迭代順序:迭代順序與 Key-Value 對的插入順序一致
3、TreeMap
TreeMap存儲 Key-Value 對時,需要根據(jù) key進行排序。TreeMap 可以保證所有的 Key-Value 對處于有序狀態(tài)。
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必須實現(xiàn) Comparable 接口,而且所有的 Key 應(yīng)該是同一個類的對象,否則將會拋出 ClasssCastException
定制排序:創(chuàng)建 TreeMap 時,傳入一個 Comparator 對象,該對象負責對 TreeMap 中的所有 key 進行排序。
TreeMap判斷兩個key相等的標準:兩個key通過compareTo()方法或者compare()方法返回0。
若使用自定義類作為TreeMap的key,所屬類需要重寫equals()和hashCode()方法,且equals()方法返回true時,compareTo()方法應(yīng)返回0。
4、Hashtable
Hashtable是個古老的 Map 實現(xiàn)類,線程安全。
與HashMap不同,Hashtable 不允許使用 null 作為 key 和 value
與HashMap一樣,Hashtable 也不能保證其中 Key-Value 對的順序
Hashtable判斷兩個key相等、兩個value相等的標準,與hashMap一致。
5、Properties
Properties 類是 Hashtable 的子類,該對象用于處理屬性文件
由于屬性文件里的 key、value 都是字符串類型,所以 Properties 里的 key 和 value 都是字符串類型
存取數(shù)據(jù)時,建議使用setProperty(String key,String value)方法和getProperty(String key)方法
Map集合框架集
本文鏈接:
本文章“Collection集合框架和map”已幫助 127 人
免責聲明:本信息由用戶發(fā)布,本站不承擔本信息引起的任何交易及知識產(chǎn)權(quán)侵權(quán)的法律責任!
本文由賦能網(wǎng) 整理發(fā)布。了解更多培訓機構(gòu)》培訓課程》學習資訊》課程優(yōu)惠》課程開班》學校地址等機構(gòu)信息,可以留下您的聯(lián)系方式,讓課程老師跟你詳細解答:
咨詢熱線:4008-569-579