




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、Java集合框架之Map實例解析1、Map概述1.1 什么是MapMap是將鍵映射到值( key-value )的對象。一個映射不能包含重復的鍵;每個鍵最多只能映射到一個值。Map 接口提供三種collection 視圖,允許以鍵集(keySet()、值集(values()或鍵-值映射關系集(entrySet()的形式查看某個映射的內容( 即獲取鍵值對的內容 )。映射順序定義為迭代器在映射的 collection 視圖上返回其元素的順序,即可以映射得到鍵、值和鍵-值的Set集合,元素的順序是由得到的Set集合所決定的。某些映射實現可明確保證其順序,如 TreeMap 類;另一些映射實現則不保證
2、順序,如 HashMap 類 。1.2 Map與Collection的區別· 1.Map 存儲的是鍵值對形式的元素,鍵唯一,值可以重復。· 2.Collection 存儲的是單列元素,子接口Set元素唯一,子接口List元素可重復。· 3.Map集合的數據結構值針對鍵有效,跟值無關,Collection集合的數據結構是針對元素有效關于Collection可以戳這里java集合框架之Collection實例解析2、Map繼承體系下面列出了常見Map集合的繼承體系與他們的特點-Map 鍵唯一 |-HashMap 基于哈希表的 Map 接口的實現。此實現提供所有可選的映
3、射操作,并允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恒久不變。 此實現不是同步的。 |-LinkedHashMap Map接口的哈希表和鏈接列表實現,具有可預知的迭代順序。此實現與 HashMap 的不同之處在于,后者維護著一個運行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,該迭代順序通常就是將鍵插入到映射中的順序(插入順序)。此實現不是同步的 |-WeakHashMap 以弱鍵 實現的基于哈希表的 Map。在 WeakHashMap 中,當某個鍵不再正
4、常使用時,將自動移除其條目。更精確地說,對于一個給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終止,然后被回收。丟棄某個鍵時,其條目從映射中有效地移除,null 值和 null 鍵都被支持。 |-Hashtable 此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非 null 對象都可以用作鍵或值。 Hashtable 是同步的 |-TreeMap 基于紅黑樹(Red-Black tree)的 NavigableMap 實現。該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序,具體取決于使用的構造方法。 此實現不是同
5、步的3、Map泛型接口Map特點 : 由key-value鍵值對組成,鍵不可重復,值可重復大致包含如下功能:· 插入(put、putAll())、刪除(remove())· 獲取(entrySet()、get()、keySet()、size()、values())· 判斷(containsKey()、containsValue()、equals()、isEmpty())、清除(clear())· 替換(replace(),replace(K key, V oldValue, V newValue) jdk1.8之后,后面示例會講到它們)方法摘要 void
6、 clear() 從此映射中移除所有映射關系(可選操作)。 boolean containsKey(Object key) 如果此映射包含指定鍵的映射關系,則返回 true。 boolean containsValue(Object value) 如果此映射將一個或多個鍵映射到指定值,則返回 true。 Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射關系的 Set 視圖。 boolean equals(Object o) 比較指定的對象與此映射是否相等。 V get(Object key) 返回指定鍵所映射的值;如果此映射不包含該鍵
7、的映射關系,則返回 null。 int hashCode() 返回此映射的哈希碼值。 boolean isEmpty() 如果此映射未包含鍵-值映射關系,則返回 true。 Set<K> keySet() 返回此映射中包含的鍵的 Set 視圖。 V put(K key, V value) 將指定的值與此映射中的指定鍵關聯(可選操作)。 void putAll(Map<? extends K,? extends V> m) 從指定映射中將所有映射關系復制到此映射中(可選操作)。 V remove(Object key) 如果存在一個鍵的映射關系,則將其從此映射中移除(可選
8、操作)。 int size() 返回此映射中的鍵-值映射關系數。 Collection<V> values() 返回此映射中包含的值的 Collection 視圖。3.1、 Map集合遍歷的常見方式方式1、根據鍵獲取值(key -> value)1.獲取所有鍵的集合2.遍歷鍵的集合,獲取到每一個鍵3.根據鍵找值方式2、根據鍵值對對象獲取鍵和值( entrySet -> key,value)1.獲取所有鍵值對對象的集合2.遍歷鍵值對對象的集合,獲取到每一個鍵值對對象3.根據鍵值對對象找鍵和值3.11 Map使用示例public class MapReview public
9、 static void main(String args) Map<String, String> map=new HashMap<String, String>(); map.put("000", "qqq"); map.put("003", "rrr"); map.put("001", "www"); map.put("002", "eee"); map.put("004", "
10、;sss"); / System.out.println(map); / 直接打印輸出鍵值對 / 遍歷1 : 通過鍵值對對象entrySet獲取鍵與值 Set<Entry<String, String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) String key = entry.getKey(); String value = entry.getValue(); System.out.println("key="+key+
11、" value="+value); System.out.println("-"); / 遍歷2:通過鍵keySet獲取值 Set<String> keySet = map.keySet(); / 得到鍵的集合 for (String key : keySet) String value = map.get(key); System.out.println("key="+key+" value="+value); System.out.println("-"); / 獲取Map值的集
12、合 Collection<String> values = map.values(); System.out.println(values); / 判斷是否存在鍵和值 System.out.println("containsKey="+map.containsKey("001"); System.out.println("containsKey="+map.containsValue("eee"); / 向Map集合添加元素時,若鍵存在,則返回之前與鍵對應的值 String put = map.put(
13、"000", "aaa"); System.out.println("put="+put); / output: qqq / default V replace(K key, V value) / 替換功能,將舊值替換成新值,并返回舊值(若有的話) String replace = map.replace("003", "666"); System.out.println("replace="+replace); System.out.println(map); / defa
14、ult boolean replace(K key, V oldValue, V newValue / 只有當鍵key存在,并且oldValue與newValue相等時,舊的值才會被替換成新的值,并且返回true boolean success = map.replace("004", "sss", "lll"); System.out.println("replace2="+success); / output : true 3.2、 HashMap的特點鍵是哈希表結構,可以保證鍵的唯一性,當向已存在key的Ma
15、p中添加元素時,會覆蓋掉舊值,并將舊值返回。它允許使用 null 值和 null 鍵,但不保證映射的順序,特別是它不保證該順序恒久不變(即不會保證存儲的順序與輸出的順序恒久不變)。 此實現不是同步的。注意:對于自定義對象,需重寫其equals和hashCode方法才能保證其key的唯一性與Hashtable的異同除了非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同的使用示例public class HashMapReview public static void main(String args) test1(); test2(); /* * 自定義類型做k
16、ey, * 需重寫其equals和hashCode方法才能保證其key的唯一性 */ private static void test2() HashMap<Info, String> map=new HashMap<Info, String>(); map.put(new Info(0, "aaa"),"0000"); map.put(new Info(1, "bbb"),"1111"); map.put(new Info(3, "ddd"),"3333&qu
17、ot;); map.put(new Info(0, "aaa"),"4444"); map.put(new Info(2, "ccc"),"2222"); printMap(map); / output:/ key=Info id=3, adress=ddd value=3333/ key=Info id=2, adress=ccc value=2222/ key=Info id=0, adress=aaa value=0000/ key=Info id=1, adress=bbb value=1111/ key=
18、Info id=0, adress=aaa value=4444 / 當Info沒有重寫equals和hashCode方法時,key出現重復元素 /* * String或基本數據類型的包裝類做key,他們已重寫了hashCode與equals方法 * 鍵唯一,重復添加會替換舊值成新值 */ private static void test1() HashMap<String, String> map=new HashMap<String, String>(); map.put("aaa", "123"); map.put(&quo
19、t;bbb", "789"); map.put("aaa", "456"); map.put("ccc", "321"); System.out.println(map); / output:/ aaa=456, ccc=321, bbb=789 / 重復的鍵不會重新插入,只會替換舊值成新值 private static void printMap(Map<Info, String> map) Set<Entry<Info, String>> ent
20、rySet = map.entrySet(); for (Entry<Info, String> entry : entrySet) System.out.println("key="+entry.getKey()+" value="+entry.getValue(); 3.24 一個HashMap面試題需求如下: 已知一個HashMap<Integer,Person>集合, Person有name(String)和age(int)屬性。 請寫一個方法實現對HashMap的排序功能。該方法接收HashMap<Integer,
21、Person>為形參,返回類型為HashMap<Integer,Person>,要求對HashMap中的Person的age升序進行排序。排序時key=value鍵值對不得拆散。分析:HashMap本身是不保證元素的順序不變的,要對其排序可使用LinkedHashMap,它是有序的并且還是HashMap的子類,我們可以使用它來完成排序的目的。最后返回它的實例即可滿足要求 并且還符合多態的編程思想 示例代碼public class SortedHashMapDemo public static void main(String args) HashMap<Integer,
22、 Person> map = new LinkedHashMap<Integer, Person>(); map.put(0, new Person("小明", 20); map.put(1, new Person("小二", 26); map.put(2, new Person("小四", 19); map.put(3, new Person("阿七", 33); map.put(4, new Person("十四", 25); map.put(4, new Person(&
23、quot;小花", 19); System.out.println(map); HashMap<Integer, Person> sortedHashMap = SortedHashMap(map); System.out.println(sortedHashMap); public static HashMap<Integer, Person> SortedHashMap( HashMap<Integer, Person> map) / 獲得鍵值對Set集合 Set<Entry<Integer, Person>> entr
24、ySet = map.entrySet(); / 將鍵值對Set集合轉化為List以用Collections來排序 List<Entry<Integer, Person>> list = new ArrayList<Map.Entry<Integer, Person>>( entrySet); / 通過Collections來排序,添加比較器,比較年齡 Collections.sort(list, new Comparator<Entry<Integer, Person>>() Override public int co
25、mpare(Entry<Integer, Person> o1, Entry<Integer, Person> o2) int result = o2.getValue().age - o1.getValue().age; result = result = 0 ? o2.hashCode() - o1.hashCode() : result; return result; ); / 創建LinkedHashMap來存儲排好序的List元素 LinkedHashMap<Integer, Person> linkedHashMap = new LinkedHa
26、shMap<Integer, Person>(); / 遍歷List,將元素添加到linkedHashMap中 for (Entry<Integer, Person> entry : list) linkedHashMap.put(entry.getKey(), entry.getValue(); return linkedHashMap; class Person String name; int age; public Person(String name, int age) super(); = name; this.age = age; Ov
27、erride public String toString() return "Person name=" + name + ", age=" + age + "" 3.3、 LinkedHashMap3.31 LinkedHashMap特點:Map接口的哈希表和鏈接列表實現,具有可預知的迭代順序。此鏈接列表定義了迭代順序(即存儲的順序與輸出的順序相同),該迭代順序通常就是將鍵插入到映射中的順序(插入順序)。此實現不是同步的注意:當key為String或基本數據類型包裝類,鍵相同自動替換舊值為新值 (因為他們已重寫了hashCode與
28、equals方法) 當key為自定義對象,需讓其重寫hashCode與equals方法才能保證key的唯一性3.32 LinkedHashMap使用示例public class LinkedHashMapReview public static void main(String args) test1(); test2(); test3(); /* * 自定義對象為key * 需讓其重寫hashCode與equals方法才能保證key的唯一性 */ private static void test3() LinkedHashMap<Info, Integer> map=n
29、ew LinkedHashMap<Info, Integer>(); map.put(new Info(0, "vvv"), 000); map.put(new Info(0, "vvv"), 333); map.put(new Info(1, "ccc"), 111); System.out.println(map); / output : 當Info沒有重寫hashCode與equals方法,/ Info id=0, adress=vvv=0, Info id=0, adress=vvv=333, Info id=1,
30、 adress=ccc=111 / output : 當Info重寫hashCode與equals方法/ Info id=0, adress=vvv=333, Info id=1, adress=ccc=111 /* * 基本數據類型包裝類重寫了hashCode與equals方法,鍵相同自動替換舊值為新值 */ private static void test2() LinkedHashMap<Integer, Integer> map=new LinkedHashMap<Integer, Integer>(); map.put(1, 66); map.put(2, 6
31、7); map.put(3, 68); map.put(1, 69); / 自動裝箱 Integer.valueOf(69) System.out.println(map); / output/ 1=69, 2=67, 3=68 / 輸出順序與存儲相同,重復添加已有的鍵會替換掉舊值 /* * String做key * String類實現了hashCode與equals方法,鍵相同自動替換舊值為新值 */ private static void test1() LinkedHashMap<String, String> map=new LinkedHashMap<String,
32、 String>(); map.put("aa", "121"); map.put("bb", "122"); map.put("cc", "123"); map.put("aa", "122"); map.put("dd", "122"); map.put("ee", "122"); System.out.println(map); / output
33、 / aa=122, bb=122, cc=123, dd=122, ee=122 / 輸出順序與存儲相同,重復添加已有的鍵會替換掉舊值 3.4、 HashtableHashtable是同步的,它不允許使用 null 值和 null 鍵。除此之外與HashMap大致相同,示例略 3.41 使用PropertiesProperties類繼承自Hashtable,表示了一個持久的屬性集,由鍵值對(key-value)組成。與Hashtable不同的是,Properties 屬性列表中每個鍵及其對應值都是一個字符串,因此不推薦使用Hashtable的put方法為Properties添加屬性
34、。Properties 可通過store方法保存在流中或通過load方法從流中加載。如下三種方式:1.通過字節輸入輸出流 void load(InputStream inStream) 從輸入流中讀取屬性列表(鍵和元素對)。 void store(OutputStream out, String comments) 以適合使用 load(InputStream) 方法加載到 Properties 表中的格式,將此 Properties 表中的屬性列表(鍵和元素對)寫入輸出流。 2.通過字符輸入輸出流 void load(Reader reader) 按簡單的面向行的格式從輸入字符流中讀取屬性列
35、表(鍵和元素對)。 void store(Writer writer, String comments) 以適合使用 load(Reader) 方法的格式,將此 Properties 表中的屬性列表(鍵和元素對)寫入輸出字符。 3.通過xmlvoid loadFromXML(InputStream in) 將指定輸入流中由 XML 文檔所表示的所有屬性加載到此屬性表中。 void storeToXML(OutputStream os, String comment) 發出一個表示此表中包含的所有屬性的 XML 文檔。 void storeToXML(OutputStream os, Strin
36、g comment, String encoding) 使用指定的編碼發出一個表示此表中包含的所有屬性的 XML 文檔。 通過如下方法存取鍵值 String getProperty(String key) 用指定的鍵在此屬性列表中搜索屬性。 String getProperty(String key, String defaultValue) 用指定的鍵在屬性列表中搜索屬性。 Object setProperty(String key, String value) 調用 Hashtable 的方法 put。 void list(PrintStream out) 將屬性列表輸出到指定的輸出流。
37、void list(PrintWriter out) 將屬性列表輸出到指定的輸出流。 Set<String> stringPropertyNames() 返回此屬性列表中的鍵集,其中該鍵及其對應值是字符串,如果在主屬性列表中未找到同名的鍵,則還包括默認屬性列表中不同的鍵。 下面通過示例使用Properties 1.創建一個屬性文件/* * 創建一個屬性文件 * throws IOException */ private static void create() throws IOException / 創建一個空的屬性文件 Properties prop = new Pr
38、operties(); / 創建一個文件輸出流,用于寫出屬性文件到本地 FileWriter writer = new FileWriter("perties");/亦可以使用FileOutputStream / 設置屬性鍵與值 prop.setProperty("name", "pecuyu"); prop.setProperty("character", "kind"); / 通過字符輸出流將鍵值對寫入屬性文件 prop.store(writer, "this
39、is new"); writer.close(); 2.讀取屬性文件內容 /* * 讀取一個屬性文件 */ private static void load() throws FileNotFoundException, IOException / 創建屬性文件 Properties prop=new Properties(); / 從流中讀取屬性列表到屬性文件 prop.load(new FileInputStream("perties");/ 亦可使用FileReader / 通過鍵取值 String name = prop.getProp
40、erty("name"); String character = prop.getProperty("character"); /System.out.println("name="+name+" character="+character); prop.list(System.out); / 將屬性鍵值對列出并打印到控制臺 Set<String> stringPropertyNames = prop.stringPropertyNames();/ 鍵的set集合 for (String key : s
41、tringPropertyNames) String value = prop.getProperty(key); / 通過鍵獲取值 System.out.println("key="+key+" value="+value); 3.5、 WeakHashMap3.51 特點以弱鍵 實現的基于哈希表的 Map。在 WeakHashMap 中,當某個鍵不再正常使用時,將自動移除其條目。更精確地說,對于一個給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終止,然后被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行為
42、與其他的 Map 實現有所不同。 null 值和 null 鍵都被支持3.52 實現注意事項WeakHashMap 中的值對象由普通的強引用保持。因此應該小心謹慎,確保值對象不會直接或間接地強引用其自身的鍵,因為這會阻止鍵的丟棄。注意,值對象可以通過 WeakHashMap 本身間接引用其對應的鍵;這就是說,某個值對象可能強引用某個其他的鍵對象,而與該鍵對象相關聯的值對象轉而強引用第一個值對象的鍵。處理此問題的一種方法是,在插入前將值自身包裝在 WeakReferences 中,如:m.put(key, new WeakReference(value),然后,分別用 get 進行解包。 3.6
43、、 TreeMap3.61 TreeMap特點- 基于紅黑樹(Red-Black tree)的 NavigableMap 實現。該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序,具體取決于使用的構造方法。- 鍵值對是紅黑樹結構,可以保證鍵的排序和唯一性- 此實現不是同步的須為TreeMap提供排序方案根據其鍵的自然順序進行排序(自定義對象須實現Comparable接口并重寫compare方法) 根據創建映射時提供的Comparator進行排序,具體取決于使用的構造方法。3.62 分析TreeMap的put方法源碼1、判斷Entry是否有元素,
44、沒有則new一個,并添加新元素 2、通過自然排序與比較器排序來為TreeMap排序,優先使用Comparator來排序通過Entry對象來來確保插入元素的唯一性,它建立在compare方法的基礎上,此方法返回0時,表示插入的鍵存在,直接替換舊值并返回。因此在使用TreeMap時,自定義對象須實現Comparable接口并重寫compare方法或在創建TreeMap時提供Comparator cmp = pare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return
45、t.setValue(value);3、在插入元素后重新調整紅黑樹(即Entry樹)源碼如下public V put(K key, V value) Entry<K,V> t = root; / 判斷Entry是否有元素,沒有則new一個 if (t = null) compare(key, key); / type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount+; return null; int cmp; Entry<K,V> pare
46、nt; / 通過自然排序與比較器排序 / split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) do parent = t; cmp = pare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); while (t != null); else if (key = null) throw
47、new NullPointerException(); SuppressWarnings("unchecked") Comparable<? super K> k = (Comparable<? super K>) key; do parent = t; cmp = pareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); while (t != null); Entry<K,V>
48、e = new Entry<>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size+; modCount+; return null; 3.63 TreeMap使用示例public class TreeMapReview public static void main(String args) test1(); test2(); /* * 自定義對象做key,需滿足以下兩個條件之一,否則拋出異常 * 實現Comparable接口
49、并重寫compare方法 * 構造TreeMap對象時,需傳入Comparator * 當兩者都有,以Comparator來排序 */ private static void test2() TreeMap<Info, String> map=new TreeMap<Info, String>(new Comparator<Info>() Override public int compare(Info o1, Info o2) int num = o2.getId() - o1.getId(); num = num = 0 ? o2.getAdress()
50、.hashCode() - o1.getAdress().hashCode() : num; return num; ); map.put(new Info(000, "hhh"), "qqq"); map.put(new Info(001, "hhh"), "aaa"); map.put(new Info(002, "hhh"), "zzz"); map.put(new Info(000, "hhh"), "qqq"); System
51、.out.println(map); /* * String類型或基本類型包裝類做key * String類實現了Comparable接口,可以進行自然排序 */ private static void test1() TreeMap<String, String> map = new TreeMap<String, String>(); map.put("a", "111"); map.put("b", "123"); map.put("c", "121&qu
52、ot;); map.put("c", "121"); Set<Entry<String, String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) System.out.println("key=" + entry.getKey() + " value=" + entry.getValue(); / output:/ key=a value=111/ key=b value=123/ key=c value=121 4、Coll
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年醫學影像師考試試卷及答案解析
- 2025年文化創新與產業轉型專業能力考核試題及答案
- 2025年師范專業英語考試試卷及答案
- 2025年社區護理管理考試試題及答案
- 2025年人才招聘與面試管理職能考核題及答案
- 2025年青少年心理健康教育知識考試卷及答案
- 2025年建筑師職業考試試題及答案列表
- 2025年教師職業能力培訓考試題及答案
- 2025年環境污染治理與技術考試試卷及答案
- 2025年道德與法治教師培訓考試試題及答案
- GB/T 19023-2025質量管理體系成文信息指南
- 電工期末復習試題含答案
- NB/T 11637-2024煤礦瓦斯抽采系統管理規范
- 2025年北京西城區九年級中考二模英語試卷試題(含答案詳解)
- 2025年金融科技應用考試試題及答案
- T/CECS 10378-2024建筑用輻射致冷涂料
- 2025年全球科技:中國無人駕駛出租車市場:商業化之路研究報告(英文版)-高盛
- 2025南京租房合同協議范本下載
- 農業光伏電站項目投資估算
- 污水處理設施運維服務投標方案(技術標)
- 三管三必須-新安法宣貫課件
評論
0/150
提交評論