java HashMap需要注意的一些地方
来源:互联网 发布:祛痘图片淘宝 编辑:程序博客网 时间:2024/05/16 15:06
以下是示例:
HashMap<Point,String> hashMap = new HashMap<Point, String>();
Point A = new Point(2,2);
hashMap.put(A,"A");//将2,2点作为Key值存入HashMap
A.x = 1;//修改A点的x值
A.y = 1;//修改A点的y值
System.out.println(hashMap.get(A));//此时结果为Null 已经找不到了
//我们试着迭代一下
System.out.println(hashMap.size());//此处为1
for(Iterator<String> iterator = hashMap.values().iterator();iterator.hasNext();){
iterator.next();
iterator.remove();
}
System.out.println(hashMap.size());//此处依旧为1 即无法销毁
所以 使用Point作为HashMap的Key时大家要注意了 这个Point应当是Final态 即不可修改的 否则将发生在HashMap中无法找到对应Value也无法迭代删除的错误
当然其他以对象作为Key值时也应当注意
原因是hashMap的索引是通过Key的hashcode进行的 当用户人为修改对象的内部属性后会造成hashcode的变化 从而造成无法取得Value的错误
以上为本人Java游戏服务器开发中一些小小的总结
*******************************************************************
Java遍历HashMap并修改(remove)
遍历HashMap的方法有多种,比如通过获取map的keySet, entrySet, iterator之后,都可以实现遍历,然而如果在遍历过程中对map进行读取之外的操作则需要注意使用的遍历方式和操作方法。
上面代码的输出结果为
通过上面的输出可以发现第一个偶数key元素已经被成功remove,异常的抛出位置是在迭代器遍历下一个元素的时候。
如果把上面高亮的遍历代码替换成keySet的方式,通过keySet的remove操作同样会在遍历下个元素时抛出异常,示例如下。
如果要实现遍历过程中进行remove操作,上面两种方式都不能使用,而是需要通过显示获取keySet或entrySet的iterator来实现。
分析原因
其实上面的三种遍历方式从根本上讲都是使用的迭代器,之所以出现不同的结果是由于remove操作的实现不同决定的。
首先前两种方法都在调用nextEntry方法的同一个地方抛出了异常
这里modCount是表示map中的元素被修改了几次(在移除,新加元素时此值都会自增),而expectedModCount是表示期望的修改次数,在迭代器构造的时候这两个值是相等,如果在遍历过程中这两个值出现了不同步就会抛出ConcurrentModificationException异常。
1、HashMap的remove方法实现
2、HashMap.KeySet的remove方法实现
3、HashMap.HashIterator的remove方法实现
以上三种实现方式都通过调用HashMap.removeEntryForKey方法来实现删除key的操作。在removeEntryForKey方法内只要移除了key modCount就会执行一次自增操作,此时modCount就与expectedModCount不一致了,上面三种remove实现中,只有第三种iterator的remove方法在调用完removeEntryForKey方法后同步了expectedModCount值与modCount相同,所以在遍历下个元素调用nextEntry方法时,iterator方式不会抛异常。
发散
1、如果是遍历过程中增加或修改数据呢?
增加或修改数据只能通过Map的put方法实现,在遍历过程中修改数据可以,但如果增加新key就会在下次循环时抛异常,因为在添加新key时modCount也会自增。
2、有些集合类也有同样的遍历问题,如ArrayList,通过Iterator方式可正确遍历完成remove操作,直接调用list的remove方法就会抛异常。
3、jdk为什么这样设计,只允许通过iterator进行remove操作?
HashMap和keySet的remove方法都可以通过传递key参数删除任意的元素,而iterator只能删除当前元素(current),一旦删除的元素是iterator对象中next所正在引用的,如果没有通过modCount、 expectedModCount的比较实现快速失败抛出异常,下次循环该元素将成为current指向,此时iterator就遍历了一个已移除的过期数据。
- java HashMap需要注意的一些地方
- Java中的一些需要注意的地方
- 一些需要注意的地方
- java语法中一些需要注意的地方
- cmd执行Java源码需要注意的一些地方
- java需要注意的地方
- Java 需要注意的地方
- 一些常需要注意的地方
- JS一些需要注意的地方
- Rose框架一些需要注意的地方
- 配库时需要注意的一些地方
- nasm汇编一些需要注意的地方
- $.ajax需要注意的一些地方
- 关于AIDL一些需要注意的地方
- python中需要注意的一些地方
- java需要注意的地方2
- Java的final变量需要注意地方
- Java引用传递需要注意的地方
- 天地否
- ZOJ2969
- ZOJ2970
- ZOJ2972动态规划
- CentOS 开机自启动脚本
- java HashMap需要注意的一些地方
- POJ1201(查分约束)
- ZOJ2976暴力法
- Apache Kafka 分布式消息队列中间件安装与配置
- 在windows, linux平台上安装 libsvm (matlab版本)
- Python 获取新浪微博指定用户的微博列表
- Centos 6.5 yum快速升级、修复OpenSSL heartbleed漏洞
- java使用反射调用set和get方法
- Map.entry优势