摘要:增強的集合都可以是任何引用類型的數(shù)據(jù),的不允許重復(fù)即同一個對象的任何兩個通過方法比較總是返回。的這些實現(xiàn)類和子接口中集的存儲形式和對應(yīng)集合中元素的存儲形式完全相同。根據(jù)的自然順序,即枚舉值的定義順序,來維護對的順序。
Java8增強的Map集合
Key-value都可以是任何引用類型的數(shù)據(jù),Map的Key不允許重復(fù)即同一個Map對象的任何兩個key通過equals方法比較總是返回false。
如果把Map里的所有key放在一起來看,他們就組成了一個Set集合:所有key沒有順序,key與key之間不能重復(fù),實際上Map確實包含了一個keySet方法,用來返回Map里所有key組成的Set集合。
Map的這些實現(xiàn)類和子接口中key集的存儲形式和對應(yīng)Set集合中元素的存儲形式完全相同。
Set與Map之間的關(guān)系非常密切。雖然Map中放的元素時key-value對,Set集合中放的元素時單個對象,但如果把key-value對中的value當(dāng)成key的附庸:key在那里,value就跟在那里,這樣就可以像對待Set一樣來對待Map了。事實上,Map提供了一個Entry內(nèi)部類來封裝key-value對,而計算Entry存儲時則只考慮Entry封裝的key。從java源碼來看,java是先實現(xiàn)了Map,然后通過包裝一個所有value都為null的Map就實現(xiàn)了Set集合。
如果把Map里的所有value放在一起來看,他們又非常類似于一個List:元素與元素之間可以重復(fù),但每個元素可以根據(jù)索引來查找,只是Map中的索引不再使用整數(shù)值,而是以另一個對象作為索引。
public class MapTest { public static void main(String[] args) { MapJava8為Map新增加的方法map = new HashMap<>(); map.put("java", 1); map.put("python", 2); map.put("hadoop", 3); //{python=2, java=1, hadoop=3} System.out.println(map); //如果當(dāng)前Map中已經(jīng)有一個與該Key相等的key-value對,則新的key-value會覆蓋原來的key-value對。并返回之前被覆蓋的value Integer put = map.put("java", 4); System.out.println(put);//1 for(Entry map2:map.entrySet()) { System.out.println(map2); //python=2 //java=4 //hadoop=3 } for(Object obj : map.keySet()) { System.out.println(obj);//python java hadoop } } }
public class NewMapTest { public static void main(String[] args) { MapJava8改進的HashMap和Hashtable實現(xiàn)類map = new HashMap<>(); map.put("123", 456); //{123=456} System.out.println(map); /** * compute 和 computeIfAbsent 和 computeIfPresent總結(jié) * * compute 如果函數(shù)式接口中的返回值不為null,那就是用接口中返回值來覆蓋原value * 如果接口中返回值為null,那么就刪除此map對 * 如果原value為null,那就用接口中返回值覆蓋原value * computeIfAbsent * 如果函數(shù)式接口中的返回值不為null,而且原value不為null,那么不做改變 * 如果接口中返回值為null,不做改變 * 如果原value為null,那么就使用接口中的返回值覆蓋原value */ /** * map.compute(key, remappingFunction) * 該方法使用remappingFunction根據(jù)原來key-value對計算一個新value * 只要新value不為null,就使用新value覆蓋原來value; * 如果原來value不為null,但新value為null,則刪除原key-value對; * 如果原value,新value同時為null,那么方法不改變?nèi)魏蝛ey-value對,直接返回null; */ /* Integer compute = map.compute("123", (key,value) -> Integer.parseInt(key)); System.out.println(compute);//123 System.out.println(map);//{123=123} Integer compute = map.compute("123", (key,value) -> null); System.out.println(map);//{} */ /* map.put("1234", null); Integer compute = map.compute("1234", (key,value) -> 0); System.out.println(compute);//0 System.out.println(map);//{123=456, 1234=0} */ /** * Absent 缺席 * map.computeIfAbsent(key, mappingFunction) * 如果傳給該方法的key參數(shù)在Map中對應(yīng)的value為null,則使用mappingFunction根據(jù)原來key,value計算一個新的結(jié)果 * 如果計算結(jié)果不為null,則用計算結(jié)果覆蓋原有的value。如果原Map原來不包括該Key,那么該方法可能會添加一組key-value對。 */ /* map.put("1234", null); map.computeIfAbsent("1234", (key) -> Integer.parseInt(key)); System.out.println(map);//{123=456, 1234=1234} */ /* Integer computeIfAbsent = map.computeIfAbsent("1231", (e) -> Integer.parseInt(e)); System.out.println(computeIfAbsent);//1231 System.out.println(map);//{123=456, 1231=1231} */ /* Integer computeIfAbsent = map.computeIfAbsent("123", (e) -> Integer.parseInt("123123123")); System.out.println(computeIfAbsent);//456 System.out.println(map);//{123=456} */ /** * Present 提出;介紹;呈現(xiàn);贈送 * map.computeIfPresent(key, remappingFunction) * 如果傳給該方法的key參數(shù)在Map中對應(yīng)的value不為null,該方法使用remappingFunction根據(jù)原key-value計算一個新結(jié)果, * 如果計算結(jié)果不為null,則使用該結(jié)果覆蓋原來的value, * 如果計算結(jié)果為null,則刪除原key-value對 */ /* Integer computeIfPresent = map.computeIfPresent("123", (key,value) -> 0); System.out.println(computeIfPresent);//0 System.out.println(map);//{123=0} */ /* Integer computeIfPresent = map.computeIfPresent("1234", (Key,value) -> 0); System.out.println(computeIfPresent);//null System.out.println(map);//{123=456} */ /* map.put("1234", null); Integer computeIfPresent = map.computeIfPresent("1234", (key,value) -> 12); System.out.println(computeIfPresent);//null System.out.println(map);//{123=456, 1234=null} */ /* Integer computeIfPresent = map.computeIfPresent("123", (key,value) -> null); System.out.println(computeIfPresent);//null System.out.println(map);//{} */ //獲取指定key對應(yīng)的value,如果key不存在那么就返回指定value Integer orDefault = map.getOrDefault("1234", 452); System.out.println(orDefault);//452 /** * 該方法會先根據(jù)key參數(shù)獲取該Map中對應(yīng)的value,如果獲取的value為null * 則直接用傳入的value覆蓋原有的value,在這種情況下,可能要添加一組map對, * 如果value不為null,則使用函數(shù)接口根據(jù)value,新value計算出一個新的結(jié)果,并用得到的結(jié)果去覆蓋原有的value */ Integer merge = map.merge("123", 123123, (key,value) -> value+1000); System.out.println(merge);//124123 System.out.println(map);//{123=124123} } }
Hashtable和HashMap區(qū)別
Hashtable是一個線程安全的Map實現(xiàn),但HashMap是線程不安全的實現(xiàn),所以HashMap比Hashtable的性能高一點,但如果有多個線程訪問同一個Map對象時,使用Hashtable實現(xiàn)類會更好、
Hashtable不允許使用null作為key和value,如果試圖把null值放入Hashtable里,將引發(fā)空指針異常,但HashMap可是使用null作為key和value、
為了成功的在HashMap,Hashtable中存儲,獲取對象,用作key的對象必須實現(xiàn)hashCode方法和equals方法。
類似于HashSet,HashMap,Hashtable判斷兩個key相等的標準也是:兩個key通過equals方法返回true,兩個key的hashCode值也相等。
HashMap和Hashtable判斷兩個value相等的標準是:只要兩個對象通過equals方法比較返回true即可。
public class ABHashtable { public static void main(String[] args) { Hashtable hashtable = new Hashtable<>(); hashtable.put(new A(123), "123"); hashtable.put(new A(1234), "1234"); hashtable.put(new A(1236), new B()); System.out.println(hashtable); System.out.println(hashtable.containsValue("32342342"));//true System.out.println(hashtable.containsKey(new A(123)));//true System.out.println(hashtable.containsKey(new A(123123)));//false } }
上述代碼解釋:上述Hashtable中包含了B對象,而且重寫了B對象的equals方法,它與任何對象通過equals都會返回true,所以在第一個輸出是true。根據(jù)Hashtable判斷兩個key相等的標準,在第二個輸出的時候,因為通過equals和hashCode都返回true,所以Hashtable判斷這兩個key相等,所以為true。
與HashSet類似的是,如果使用可變對象作為HashMap,Hashtable的key,如果程序修改了可變對象,那么程序再也無法準確訪問到Map中被修改過的key。
public class ABHashtable2 { public static void main(String[] args) { HashMap hashtable = new HashMap(); hashtable.put(new A(123), "123"); hashtable.put(new A(1234), "1234"); //{mapTest.A@4d2=1234, mapTest.A@7b=123} System.out.println(hashtable); A next = (A) hashtable.keySet().iterator().next(); System.out.println(next.count);//1234 next.count = 123; //{mapTest.A@7b=1234, mapTest.A@7b=123} System.out.println(hashtable); hashtable.remove(new A(123)); //只能刪除沒有被修改的key所對應(yīng)的key-value對 System.out.println(hashtable);//{mapTest.A@7b=1234} System.out.println(hashtable.get(new A(123)));//null } }
盡量不要使用可變對象作為key,如果確實需要,則盡量不要在程序中修改作為key的對象。
LinkedHashMap實現(xiàn)類LinkedHashMap也使用雙向鏈表來維護key-value對的次序,其實只需要考慮key的次序,該鏈表負責(zé)維護Map的迭代順序,迭代順序與key-value對的插入順序保持一致。
因為他使用鏈表來維護內(nèi)部順序,所以在迭代訪問Map里的全部元素時將有較好的性能,迭代輸出LinkedHashMap的元素時,將會安添加key-value的順序輸出。
public class LinkedHashMapS { public static void main(String[] args) { LinkedHashMap map = new LinkedHashMap<>(); map.put("1", "1"); map.put("2", "2"); map.put("3", "3"); System.out.println(map);//{1=1, 2=2, 3=3} } }使用Properties讀寫屬性文件
Properties是Hashtable類的子類
Properties相當(dāng)于一個key,value都是String的Map
public class PropertiesTest { public static void main(String[] args) throws FileNotFoundException, IOException { Properties properties = new Properties(); properties.setProperty("w","zq"); properties.setProperty("w1","zq1"); properties.setProperty("w2","zq2"); //輸出文件目錄,文件說明 properties.store(new FileOutputStream(new File("myProperties.properties")), "comment"); properties.storeToXML(new FileOutputStream(new File("myProperties1.xml")), "comment"); } } myProperties #comment #Fri Mar 09 10:11:42 CST 2018 w=zq w1=zq1 w2=zq2 myProperties1SortedMap接口和TreeMap實現(xiàn)類comment zq zq1 zq2
TreeMap就是一個紅黑樹數(shù)據(jù)結(jié)構(gòu),每個key-value對即作為紅黑樹的一個節(jié)點。TreeMap存儲key-value對時,需要根據(jù)key對節(jié)點進行排序。TreeMap可以保證所有的key-value對處于有序狀態(tài)。TreeMap也可以自然排序和定制排序。
TreeMap中判斷兩個key相等的標準是:兩個key通過compareTo方法返回0,TreeMap即認為這兩個key是相等的。
如果使用自定義類作為TreeMap的key,且想讓TreeMap良好的工作,則重寫該類的equals方法和compareTo方法時保持一致的返回結(jié)果。
Set和Map的關(guān)系十分密切,java源代碼就是先實現(xiàn)了HashMap,TreeMMap等集合,然后通過包裝一個所有的value都為null的Map集合實現(xiàn)了Set集合類。
public class TreeMapTest { public static void main(String[] args) { TreeMap treeMap = new TreeMap<>(); treeMap.put(12, 34); treeMap.put(-12, 34); treeMap.put(122, 34); treeMap.put(0, 34); //{-12=34, 0=34, 12=34, 122=34} System.out.println(treeMap); } }WeakHashMap實現(xiàn)類
WeakHashMap與HashMap的區(qū)別是:HashMap的key保留對實際對象的強引用,這意味著只要該HashMap對象不被銷毀,該HashMap的所有key所引用的對象就不會被垃圾回收,HashMap也不會自動刪除這些key所對應(yīng)的key-value對;但WeakHashMap的key只保留了實際對象的弱引用,這意味著如果WeakHashMap對象的key所引用的對象沒有被其他強引用變量所引用,則這些key所引用的對象可能被垃圾回收,WeakHashMap也可能自動刪除這些key所對應(yīng)的key-value對。
public class WeakHashMapTets { public static void main(String[] args) { WeakHashMap weakHashMap = new WeakHashMap<>(); weakHashMap.put(new String("1"), new String("1")); weakHashMap.put(new String("2"), new String("2")); weakHashMap.put(new String("3"), new String("3")); weakHashMap.put("4", new String("4")); //{4=4, 1=1, 2=2, 3=3} System.out.println(weakHashMap); System.gc(); System.runFinalization(); //{4=4} System.out.println(weakHashMap); //第四組key-value對的key是一個字符串直接量,系統(tǒng)會自動保留對該字符串對象的強引用,所以垃圾回收時不會回收他 } }
如果需要使用WeakHashMap的key來保留對象的弱引用,則不要讓該key所引用的對象具有任何強引用了否則將失去WeakHashMap的意義。
IdentityHashMap實現(xiàn)類在IdentityHashMap中,當(dāng)且僅當(dāng)兩個key嚴格相等key1 == key2時,IdentityHashMap才認為兩個key相等,對于普通的HashMap而言,只要key1和key2通過equals方法比較返回true,且他們的hashCode值相等即可。
public class IdentityHashMapTest { public static void main(String[] args) { IdentityHashMap identityHashMap = new IdentityHashMap<>(); identityHashMap.put(new String("r"),"r"); identityHashMap.put(new String("r"),"r"); identityHashMap.put("java", 0); identityHashMap.put("java", 1); //{java=1, r=r, r=r} System.out.println(identityHashMap); /** * 由于上面new String()的地址值不一樣,IdentityHashCode返回值會不一樣 * 所以第一個String與第二個String并不一樣 * 但是java字符串直接量是一樣的,所以第二次put就會覆蓋原來的value */ } }EnumMap實現(xiàn)類
EnumMap中的所有key都必須是單個枚舉類的枚舉值,創(chuàng)建EnumMap時必須顯示或隱式指定它對應(yīng)的枚舉類。
EnumMap具有如下特征
EnumMap在內(nèi)部以數(shù)組形式保存,所以這種實現(xiàn)形式非常緊湊,高效。
EnumMap根據(jù)key的自然順序,即枚舉值的定義順序,來維護key-value對的順序。
EnumMap不允許使用null作為key,但允許使用null作為value,如果試圖使用null作為key時將拋出空指針異常。如果只是查詢是否包含值為null的key,或只是刪除值為null的key,都不會拋出異常。
創(chuàng)建EnumMap時必須指定一個枚舉類,從而將該EnumMap和指定的枚舉類關(guān)聯(lián)起來。
public class EnumMapTest { public static void main(String[] args) { EnumMap enumMap = new EnumMap(EnumMaps.class); System.out.println(enumMap);//{} enumMap.put(WINTER, "4"); enumMap.put(SPRING, "4"); enumMap.put(SUMMER, "4"); //{SPRING=4, SUMMER=4, WINTER=4} System.out.println(enumMap); } }各Map實現(xiàn)類的性能分析
HashMap和Hashtable的實現(xiàn)機制幾乎一樣,但由于Hashtable是一個古老的,線程安全的集合,因此HashMap通常比Hashtable要快。
TreeMap通常比HashMap,Hashtable要慢,尤其在插入刪除key-value對時更慢,因為TreeMap底層采用紅黑樹來管理key-value對,紅黑樹的每個節(jié)點就是一個key-value對。
使用TreeMap有一個好處:TreeMap中的key-value對總是處于有序狀態(tài),無需專門進行排序操作。當(dāng)TreeMap被填充之后,就可以調(diào)用keySet(),去的由key組成的Set,然后使用toArry()方法生成key的數(shù)組,接下來使用Arrays的binarySearch()方法在已排序的數(shù)組中快速地查詢對象。
對于一般的應(yīng)用場景,程序應(yīng)該多考慮使用HashMap,因為HashMap正是為快速查詢設(shè)計的:HashMap底層其實也是采用數(shù)組來存儲key-value對。但如果程序需要一個總是排序好的Map時,則可以考慮使用TreeMap。
LinkedHashMap比HashMap慢一點,因為他需要維護鏈表來保持Map中key-value時的添加順序。IdentityHashMap心梗沒有特別出色之處,因為他采用與HashMap基本相似的實現(xiàn),只是它使用==而不是equals方法來判斷元素相等。EnumMap的性能最好,但它只能使用同一個枚舉類的枚舉值作為key。
HashSet和HashMap的性能選項對于HashSet及其子類而言,它們采用hash算法來決定集合中元素的存儲位置,并通過hash算法來控制集合的代銷;對于HashMap,Hashtable及其子類而言,他們采用hash算法來決定Map中key的存儲,并通過hash算法
設(shè)置不可變集合public class NoModifyCollections { //不可變對象都不可以增加和刪除操作 public static void main(String[] args) { //創(chuàng)建一個空的不可變的List對象 ListJava9 增加的不可變集合
public class NoModifyCollections9 { public static void main(String[] args) { List繁瑣的接口Enumerationof = List.of(""); Set of2 = Set.of(""); Map of3 = Map.of("1","2","3","4"); System.out.println(of3);//{3=4, 1=2} Map ofEntries = Map.ofEntries(Map.entry("", "")); System.out.println(ofEntries);//{=} } }
繁瑣的接口Enumeration:只能遍歷Vector和Hashtable這種老java類
public class EnumerationTeST { public static void main(String[] args) { Vectorvector = new Vector(); vector.add("3"); vector.add("2"); vector.add("1"); Enumeration elements = vector.elements(); while (elements.hasMoreElements()) { System.out.println(elements.nextElement()); // 3 2 1 } } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69317.html
摘要:使用默認隨機源對指定列表進行置換。將集合排序使用二分搜索法搜索指定列表,以獲得指定對象根據(jù)元素的自然順序,返回給定的最大元素。 1_Map集合概述和特點 A:Map接口概述 查看API可以知道: 將鍵映射到值的對象 一個映射不能包含重復(fù)的鍵 每個鍵最多只能映射到一個值 B:Map接口和Collection接口的不同 Map是雙列的,Collection是單列的 Map...
摘要:第三階段常見對象的學(xué)習(xí)集合框架集合在實際需求中,我們常常會遇到這樣的問題,在諸多的數(shù)據(jù)中,通過其編號來尋找某一些信息,從而進行查看或者修改,例如通過學(xué)號查詢學(xué)生信息。面試題和的區(qū)別是單列集合的頂層接口,有子接口和。 第三階段 JAVA常見對象的學(xué)習(xí) 集合框架——Map集合 showImg(https://segmentfault.com/img/remote/1460000019683...
package com.itheima.demo03.Map; import java.util.HashMap;import java.util.LinkedHashMap; /* java.util.LinkedHashMap entends HashMap Map 接口的哈希表和鏈接列表實現(xiàn),具有可預(yù)知的迭代順序。 底層原理: 哈希表+鏈表(記錄元素的順序) */public cla...
摘要:中的集合稱為單列集合,中的集合稱為雙列集合。洗牌通過數(shù)字完成洗牌發(fā)牌發(fā)牌將每個人以及底牌設(shè)計為將最后張牌直接存放于底牌,剩余牌通過對取模依次發(fā)牌。存放的過程中要求數(shù)字大小與斗地主規(guī)則的大小對應(yīng)。 01Map集合概述 A:Map集合概述: 我們通過查看Map接口描述,發(fā)現(xiàn)Map接口下的集合與Collection接口下的集合,它們存儲數(shù)據(jù)的形式不同 ? a:Collection中的集...
摘要:通常使用矢代器來實現(xiàn)遍歷集合。將集合中指定索引位置的對象改成指定的對象。三元運算如果否則集合沒有繼承接口,它是提供到的映射,來決定遍歷對象的順序。 showImg(/img/bVldsA); 1.Collection接口是層次結(jié)構(gòu)中的跟接口。Collection接口通常不能直接使用,但該接口提供了添加元素,刪除元素,管理數(shù)據(jù)的方法。 Collection通常使用矢代器(Iterato...
摘要:返回值存在返回對應(yīng)的值不存在返回創(chuàng)建集合對象趙麗穎楊穎林志玲楊穎迪麗熱巴把指定的鍵所對應(yīng)的鍵值對元素在集合中刪除,返回被刪除元素的值。 package com.itheima.demo01.Map; import java.util.HashMap;import java.util.Map; /* java.util.Map集合 Map集合的特點: 1.Map集合是一個雙列集合...
閱讀 1628·2021-10-12 10:11
閱讀 3747·2021-09-03 10:35
閱讀 1439·2019-08-30 15:55
閱讀 2122·2019-08-30 15:54
閱讀 993·2019-08-30 13:07
閱讀 1004·2019-08-30 11:09
閱讀 569·2019-08-29 13:21
閱讀 2645·2019-08-29 11:32