Java HashMap 如何正确遍历并删除元素的方法小结
(一)HashMap的遍历
HashMap的遍历主要有两种方式:
第一种采用的是foreach模式,适用于不需要修改HashMap内元素的遍历,只需要获取元素的键/值的情况。
HashMapmyHashMap; for(Map.entry item:myHashMap.entrySet()){ Kkey=item.getKey(); Vval=item.getValue(); //todowithkeyandval //WARNING:DONOTCHANGEkeyANDvalIFYOUWANTTOREMOVEITEMSLATER }
第二种采用迭代器遍历,不仅适用于HashMap,对其它类型的容器同样适用。
采用这种方法的遍历,可以用下文提及的方式安全地对HashMap内的元素进行修改,并不会对后续的删除操作造成影响。
for(Iterator>it=myHashMap.entrySet().iterator;it.hasNext();){ Map.Entry item=it.next(); Kkey=item.getKey(); Vval=item.getValue(); //todowithkeyandval //youmayremovethisitemusing"it.remove();" }
(二)HashMap之删除元素
如果采用第一种的遍历方法删除HashMap中的元素,Java很有可能会在运行时抛出异常。
HashMapmyHashMap=newHashMap<>(); myHashMap.put("1",1); myHashMap.put("2",2); for(Map.Entry item:myHashMap.entrySet()){ myHashMap.remove(item.getKey()); } for(Map.Entry item:myHashMap.entrySet()){ System.out.println(item.getKey());
运行上面的代码,Java抛出了java.util.ConcurrentModificationException的异常。并附有如下信息。
atjava.util.HashMap$HashIterator.nextNode(UnknownSource)
atjava.util.HashMap$EntryIterator.next(UnknownSource)
atjava.util.HashMap$EntryIterator.next(UnknownSource)
可以推测,由于我们在遍历HashMap的元素过程中删除了当前所在元素,下一个待访问的元素的指针也由此丢失了。
所以,我们改用第二种遍历方式。
代码如下:
for(Iterator>it=myHashMap.entrySet().iterator();it.hasNext();){ Map.Entry item=it.next(); //...todowithitem it.remove(); } for(Map.Entry item:myHashMap.entrySet()){ System.out.println(item.getKey()); }
运行结果没有显示,表明HashMap中的元素被正确删除了。
(三)在HashMap的遍历中删除元素的特殊情况
上述方法可能足以应付多数的情况,但是如果你的HashMap中的键值同样是一个HashMap,假设你需要处理的是HashMap
这时,单单依靠迭代器的remove()方法是不足以将该元素删除的。
例子如下:
HashMap,Integer>myHashMap=newHashMap<>(); HashMap temp=newHashMap<>(); temp.put("1",1); temp.put("2",2); myHashMap.put(temp,3); for(Iterator ,Integer>> it=myHashMap.entrySet().iterator();it.hasNext();){ Map.Entry ,Integer>item=it.next(); item.getKey().remove("1"); System.out.println(myHashMap.size()); it.remove(); System.out.println(myHashMap.size()); }
结果如下:
1
1
虽然it.remove();被执行,但是并没有真正删除元素。
原因在于期望删除的元素的键值(即HashMap
解决方案:
既然在这种情况下,HashMap中被修改过的元素不能被删除,那么不妨直接把待修改的元素直接删除,再将原本所需要的“修改过”的元素加入HashMap。
想法很好,代码如下:
for(Iterator,Integer>> it=myHashMap.entrySet().iterator();it.hasNext();){ Map.Entry ,Integer>item=it.next(); //item.getKey().remove("1"); HashMap to_put=newHashMap<>(item.getKey()); to_put.remove("1"); myHashMap.put(to_put,item.getValue()); System.out.println(myHashMap.size()); it.remove(); System.out.println(myHashMap.size()); }
但是依然是RE:
Exceptioninthread"main"java.util.ConcurrentModificationException
atjava.util.HashMap$HashIterator.remove(UnknownSource)
原因在于,迭代器遍历时,每一次调用next()函数,至多只能对容器修改一次。上面的代码则进行了两次修改:一次添加,一次删除。
既然java.util.ConcurrentModificationException异常被抛出了,那么去想办法拿掉这个异常即可。
最后的最后,我决定弃HashMap转投ConcurrentHashMap。将myHashMap定义为ConcurrentHashMap之后,其它代码不动。
运行结果如下:
2
1
最终,通过ConcurrentHashMap和一些小技巧的使用,变形实现了对被修改过键值的元素的删除。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。