简单的例子
package collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class TestRemoveMap {
static Map<String, Set<String>> map = new HashMap<String, Set<String>>();
static{
Set<String> set = new HashSet<String>();
map.put("company", set);
set.add("zte");
set.add("huawei");
set.add("ericcson");
Set<String> set1 = new HashSet<String>();
map.put("food", set1);
set1.add("rice");
Set<String> set2 = new HashSet<String>();
map.put("people", set2);
set2.add("zhangsan");
set2.add("lisi");
Set<String> set3 = new HashSet<String>();
map.put("aa", set3);
set3.add("bb");
set3.add("vv");
Set<String> set4 = new HashSet<String>();
map.put("dd", set4);
set4.add("ee");
set4.add("ff");
Set<String> set5 = new HashSet<String>();
map.put("co1mpany", set5);
set5.add("zte");
set5.add("huawei");
set5.add("ericcson");
Set<String> set6 = new HashSet<String>();
map.put("compan7y", set);
set6.add("zte");
set6.add("huawei");
set6.add("ericcson");
Set<String> set7 = new HashSet<String>();
map.put("compa7ny", set);
set7.add("zte");
set7.add("huawei");
set7.add("ericcson");
}
public static void removeMapByMeaning(String value){
for(Entry<String, Set<String>> entry : map.entrySet()){
if(entry.getValue().contains(value)){
if(entry.getValue().size()==1){
map.remove(entry.getKey());
}else{
entry.getValue().remove(value);
}
}
}
}
public static void main(String[] args) {
removeMapByMeaning("lisi");
System.out.println(map);
removeMapByMeaning("rice");
System.out.println(map);
removeMapByMeaning("ff");
System.out.println(map);
}
}
输出:
{aa=[bb, vv], dd=[ee, ff], company=[huawei, zte, ericcson], people=[zhangsan], co1mpany=[huawei, zte, ericcson], food=[rice], compan7y=[huawei, zte, ericcson], compa7ny=[huawei, zte, ericcson]}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
at collection.TestRemoveMap.removeMapByMeaning(TestRemoveMap.java:56)
at collection.TestRemoveMap.main(TestRemoveMap.java:72)
原理分析:for(Entry<String, Set<String>> entry : map.entrySet())这种for each循环,原理还是使用的迭代器iterator
1.首先看下迭代器的实例化
HashIterator() {
expectedModCount = modCount;
Node<K,V>[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
do {} while (index < t.length && (next = t[index++]) == null);
}
}
会将一个modCount赋值给一个expectedModCount变量,modCount的含义就是map被修改的次数,增加,删除元素都会修改modCount的值,取元素和修改元素的时候不变。
2.循环中取下一个元素的代码(next()函数)
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
直接了nextNode()函数
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
看到了该异常的出处,因为在遍历的时候,增删map本身的元素会修改countMod的值。
正确的删除方式是使用迭代器的remove函数来删除map中的元素。
package collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class TestRemoveMap {
static Map<String, Set<String>> map = new HashMap<String, Set<String>>();
static{
Set<String> set = new HashSet<String>();
map.put("company", set);
set.add("zte");
set.add("huawei");
set.add("ericcson");
Set<String> set1 = new HashSet<String>();
map.put("food", set1);
set1.add("rice");
Set<String> set2 = new HashSet<String>();
map.put("people", set2);
set2.add("zhangsan");
set2.add("lisi");
Set<String> set3 = new HashSet<String>();
map.put("aa", set3);
set3.add("bb");
set3.add("vv");
Set<String> set4 = new HashSet<String>();
map.put("dd", set4);
set4.add("ee");
set4.add("ff");
Set<String> set5 = new HashSet<String>();
map.put("co1mpany", set5);
set5.add("zte");
set5.add("huawei");
set5.add("ericcson");
Set<String> set6 = new HashSet<String>();
map.put("compan7y", set);
set6.add("zte");
set6.add("huawei");
set6.add("ericcson");
Set<String> set7 = new HashSet<String>();
map.put("compa7ny", set);
set7.add("zte");
set7.add("huawei");
set7.add("ericcson");
}
public static void removeMapByMeaning(String value){
for(Entry<String, Set<String>> entry : map.entrySet()){
if(entry.getValue().contains(value)){
if(entry.getValue().size()==1){
map.remove(entry.getKey());
}else{
entry.getValue().remove(value);
}
}
}
}
public static void rightRemoveMap(String value){
Iterator<Entry<String, Set<String>>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, Set<String>> entry = iterator.next();
if(entry.getValue().contains(value)){
if(entry.getValue().size()==1){
iterator.remove();
}else{
Iterator<String> iterator2 = entry.getValue().iterator();
while(iterator2.hasNext()){
if(value.equals(iterator2.next())){
iterator2.remove();
}
}
}
}
}
}
public static void main(String[] args) {
rightRemoveMap("lisi");
System.out.println(map);
rightRemoveMap("rice");
System.out.println(map);
rightRemoveMap("ff");
System.out.println(map);
}
}