java - Map使用笔记

来源:互联网 发布:java读写xml文件 编辑:程序博客网 时间:2024/06/05 11:19

Map类简介:

可以实现key-value的结构;

HashMap    根据key的hash分配地址,所以key不可重复  &  存储是无序的;

IdentityHashMap     key可以重复 

TreeMap     按照key升序分布,key不可重复

Map使用实例

遍历时更新Map , 抛出异常ConcurrentModificationException

Map<String, String> myMap = new IdentityHashMap<String, String>();/*初始化*/myMap.put("a","aa");myMap.put("b","bb");myMap.put("c","cc");myMap.put("d","dd");for(Map.Entry<String, String> entry: myMap.entrySet()){String k = entry.getKey().toString();String v = entry.getValue().toString();if(k == "b"){myMap.remove(k);  /*失败,抛出异常ConcurrentModificationException*/}}

道听途说,修改代码,用迭代器遍历:
Iterator<Entry<String, String>> it = myMap.entrySet().iterator();while (it.hasNext()) {    Map.Entry entry = (Map.Entry) it.next();    String k = entry.getKey().toString();    if(k.indexOf("b")!=-1) {    it.remove();         /*成功*/    //myMap.remove(k);   /*失败,抛出异常ConcurrentModificationException*/    }}

原因分析:

为了防止在遍历Map的时候对象被其它线程改动,Map类引入参数modCount(记录Map结构变化的次数)。
IdentityHashMap.put(K key, V value)与IdentityHashMap.remove(Object key)等都会导致modCount++。
当遍历时发现modCount变化了(modCount != expectedModCount),就会抛出异常ConcurrentModificationException。

而it.remove();成功,是因为Iterator.remove()方法会在删除当前迭代对象的同时维护索引的一致性 并且 重新同步modCount值;

解决方案:

/** * 解决方案: * 深度clone出来tmpMap,遍历tmpMap同时修改myMap * (浅度克隆:只是复制对象的引用,指向同一内存(如)) * */Map<String,String> tmpMap = new IdentityHashMap<String, String>();tmpMap.putAll(myMap);for(Map.Entry<String, String> entry: myMap.entrySet()){if(entry.getKey().toString() == "c") myMap.put("cc", "ccc");/*遍历tmpMap,修改myMap*/}



那么for-each与Iterator有什么区别?

没区别,java的for-each其实也是利用Iterator迭代。
如:此处执行流程一模一样(entrySet().iterator().nextIndex()),两者等同,只是更加简洁而已。


Map排序

若Map的key是不重复的,直接赋值给TreeMap

若Map的key是重复的

未完待续...





原创粉丝点击