HashSet的addAll方法與UnsupportedOperationException異常
前幾天使用 HashSet 時(shí)遇到了一個(gè) java.lang.UnsupportedOperationException 異常,在網(wǎng)上看了看前輩們的總結(jié),再加上自己對(duì) JDK 中相關(guān) API 的學(xué)習(xí),將出現(xiàn)該異常的原因基本弄清楚了?,F(xiàn)在用一個(gè)簡(jiǎn)短的小實(shí)例演示這個(gè)異常的出現(xiàn):2 Map<String, String> m2 = new HashMap<String, String>();
3
4 m1.put("foo", "foo");
5 m2.put("bar", "bar");
6
7 Set<String> s = m1.keySet();
8 s.addAll(m2.keySet());
9 //s.add("konglong");
10
11 /*Set<String> s = new HashSet<String>();
12 s.addAll(m1.keySet());
13 s.addAll(m2.keySet());*/
14
15 System.out.println(s);
注釋掉第 8 行,釋放第 9 行或者注釋掉第 9 行,釋放第 8 行,運(yùn)行,就會(huì)發(fā)生 java.lang.UnsupportedOperationException 異常;但是如果注釋掉第8、9行代碼,釋放第11、12、13行代碼則不會(huì)出現(xiàn)該異常。原因主要在于引用 s 所指向的 Set 對(duì)象是 HashMap.keySet 方法的返回值,此方法在 JDK 文檔中的描述為:
- Returns a
Set
view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are #ff0000. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.
從上述描述中得知此方法返回的是當(dāng)前 HashMap 對(duì)象中所包含的 key 的視圖,這個(gè)視圖是以什么格式保存的呢?它是以一個(gè) HashSet 對(duì)象的格式(形式)保存的,也就是將一個(gè)一個(gè)的鍵值封裝到一個(gè) HashSet 對(duì)象中。但是并不意味著返回的這個(gè) HashSet 對(duì)象就和原來(lái)的那個(gè) HashMap 對(duì)象一刀兩斷,毫無(wú)干系了,它們?nèi)匀慌簲嘟z連,相互影響著。這個(gè) HashSet 對(duì)象是由原來(lái)那個(gè) HashMap 對(duì)象在背后默默無(wú)聞地支持著。所以你對(duì)原來(lái)那個(gè) HashMap 對(duì)象所做的修改會(huì)映射到這個(gè) HashSet 對(duì)象,反之,對(duì)這個(gè) HashSet 對(duì)象的修改亦會(huì)映射到原來(lái)那個(gè) HashMap 對(duì)象。如果在對(duì)這個(gè) set 對(duì)象進(jìn)行迭代的同時(shí)修改了映射(但是通過(guò)迭代器自己的 remove 操作除外),則迭代結(jié)果是不確定的。該 set 支持元素的移除,通過(guò) Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作可從該映射中移除相應(yīng)的映射關(guān)系。但是它不支持 add 或 addAll 操作。
我們可以淺嘗輒止,就此止步。但是很多時(shí)候我們稍稍堅(jiān)持一下就可以得到更多的回報(bào)。它為什么不支持 add 或 addAll 操作呢?因?yàn)槿绻С诌@些操作,那么原來(lái)的 map 對(duì)象中必然多了幾個(gè) key,但是你不能只 put key 值進(jìn)去,而沒(méi)有對(duì)應(yīng)的 value 值,這違背了映射本身的數(shù)據(jù)結(jié)構(gòu)。
下一篇我將用實(shí)例演示一下通過(guò) keySet() 方法返回的 Set 對(duì)象和它源自的 Map 對(duì)象之間的相互作用。
posted on 2009-08-10 11:55 黃土高坡 閱讀(738) 評(píng)論(0) 編輯 收藏