Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同时向HashMap添加元素_Java_String_Multithreading_Collections_Concurrency - Fatal编程技术网

Java 同时向HashMap添加元素

Java 同时向HashMap添加元素,java,string,multithreading,collections,concurrency,Java,String,Multithreading,Collections,Concurrency,如果我迭代一个标准的HashMap,并尝试在迭代时向其添加元素,我会得到ConcurrentModificationException 因此,我尝试使用允许并发添加的哈希映射: ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>(); cMap.put("one", 1); cMap.forEach((key, value) -> cMap.put(key + key, value +

如果我迭代一个标准的
HashMap
,并尝试在迭代时向其添加元素,我会得到
ConcurrentModificationException

因此,我尝试使用允许并发添加的哈希映射:

ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>();
cMap.put("one", 1);
cMap.forEach((key, value) -> cMap.put(key + key, value + value));
System.out.println(cMap);
如果将键更改为zx(
cMap.put(“zx”,1)
),则现在的结果是:

{zxzx=2, zx=1}
问题:

1) 为什么会发生这种情况?两个并发操作(迭代和添加)不应冲突

2) 如何修复不一致性

与集合相反,在迭代字符串的字符时更改字符串时,不会遇到此问题:

        String str = scanner.next();
        for (int i = 1; i < str.length(); i++) {
            if (str.charAt(i) == str.charAt(i-1)) {
                str = str.substring(0, i-1) + str.substring(i+1);
                i = 0;
            }
        }
        if (str.length() == 0) {
            System.out.println("Empty String");
        } else {
            System.out.println (str);
        }
    }
String str=scanner.next();
对于(int i=1;i
注意,在上面的循环中,源字符串实际上没有更改,而是重新分配,因为字符串是不可变的,不能修改


上述代码运行良好且一致。这就是为什么字符串是线程安全的一个例子吗?

这取决于添加新元素的哈希桶。在第一个示例中,新元素被添加到比您正在处理的哈希桶更晚的哈希桶中,迭代器尚未到达该哈希桶。在第二个示例中,新元素被添加到迭代器已经读取的早期散列桶中


在迭代过程中,你应该非常小心地修改集合。在您的情况下,最好将新条目添加到一个新映射中,然后将它们合并在一起。

这取决于添加新元素的哈希桶。在第一个示例中,新元素被添加到比您正在处理的哈希桶更晚的哈希桶中,迭代器尚未到达该哈希桶。在第二个示例中,新元素被添加到迭代器已经读取的早期散列桶中


在迭代过程中,你应该非常小心地修改集合。在您的情况下,最好将新条目添加到新地图中,然后将它们合并在一起。

这不仅仅是“最有可能”。实际上,您可以在输出中看到散列存储桶顺序:
one
首先添加,迭代器读取它,code添加
oneone
,最终在后面的存储桶中,迭代器读取它,code添加
oneoneone
,最终在更后面的存储桶中,迭代器读取它,代码添加
oneone
,它最终位于
one
前面的一个桶中,因此迭代器结束。地图的默认大小意味着在这些小示例中不会发生重新灰化。这不仅仅是“最有可能”。实际上,您可以在输出中看到散列存储桶顺序:
one
首先添加,迭代器读取它,code添加
oneone
,最终在后面的存储桶中,迭代器读取它,code添加
oneoneone
,最终在更后面的存储桶中,迭代器读取它,代码添加
oneone
,它最终位于
one
前面的一个桶中,因此迭代器结束。地图的默认大小意味着在这些小示例中不会发生重新灰化。我知道,我已经看到了那个示例…@Holger你在一篇文章中引用了你在本地Java组上发表的评论(这导致了我们有时在这里做的
OOM
):)重新阅读againI知道的内容真是太棒了,我看到过这样的例子…@Holger你在一篇文章中被引用了你在一个本地Java组上的评论(这导致了一个
OOM
),我们在这里有时会这样做:)再次阅读这篇文章真是太棒了
        String str = scanner.next();
        for (int i = 1; i < str.length(); i++) {
            if (str.charAt(i) == str.charAt(i-1)) {
                str = str.substring(0, i-1) + str.substring(i+1);
                i = 0;
            }
        }
        if (str.length() == 0) {
            System.out.println("Empty String");
        } else {
            System.out.println (str);
        }
    }