首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >你知道为什么我在从HashMap中删除密钥的时候没有得到java.util.ConcurrentModificationException吗?

你知道为什么我在从HashMap中删除密钥的时候没有得到java.util.ConcurrentModificationException吗?
EN

Stack Overflow用户
提问于 2020-02-07 05:30:46
回答 4查看 86关注 0票数 0

我想要实现的是,如果removed.Change是key,那么key就是当前时间的key,但它的值应该是相同的。

我的代码片段是:

代码语言:javascript
复制
public class hello
{
    private static HashMap<String,String> fileMap;
    private static final String KEY_REMOVED = "d";
    static {
        fileMap = new HashMap<String, String>();
        fileMap.put("a", "hello");
        fileMap.put(KEY_REMOVED, "bye");
        fileMap.put("c", "hi");
    }

    public static void main(String []args){
        upload();
}

    private static void upload() throws  ConcurrentModificationException {

        for (Map.Entry<String, String> entry : fileMap.entrySet()) {
            System.out.println("Uploading key " + entry.getKey());

            String fileName = entry.getKey();

            if (fileName.equals(KEY_REMOVED)) {
                fileName = new Timestamp(System.currentTimeMillis()).getTime();
                String temp2 = fileMap.remove(VIDEO_MP4_ASSET);
                System.out.println("hashmap after removing key is " + fileMap);
                System.out.println("adding  key to hashmap " + fileName);
                fileMap.put(fileName, temp2);

            } else {

                System.out.println("continue");
            }
            System.out.println("hashmap is " + fileMap);
        }
    }

理想情况下,在删除键时,我们应该得到ConcurrentModificationException.I。我担心我没有得到正确的结果,我的代码可能会破坏later.Is it?

EN

回答 4

Stack Overflow用户

发布于 2020-02-07 05:39:54

这可能有点混乱,因为Javadoc首先声明

这个类的所有“集合视图方法”(values()keySet()entrySet())返回的迭代器都是快速失效的:如果在创建迭代器之后的任何时候对映射进行了结构化修改,除了通过迭代器自己的方法之外,任何方式都可以修改映射,那么迭代器将抛出一个ConcurrentModificationException

请注意,无法保证迭代器的快速失效行为。

但它也在HashMap.entrySet()上声明

返回此映射中包含的映射的集合视图。该集合由地图支持,因此对地图的更改将反映在该集合中,反之亦然。如果在集合上进行迭代时修改了映射,则为(除非通过迭代器自己的remove操作,或者通过迭代器返回的映射条目上的setValue操作)迭代的结果未定义。

现在未定义的确实包括抛出一个ConcurrentModificationException,但是有一些many cases没有抛出,因为正如在开始时所看到的,快速失败行为不能保证

因此,如果您在keySet()values()entrySet()上迭代,并且您正在结构化地修改Map,即使用新的键(而不是替换现有键的值)来修改remove()put,那么您可能会得到:ConcurrentModificationException或迭代过程中发生的奇怪事情,例如跳过元素或遇到两次元素。

票数 2
EN

Stack Overflow用户

发布于 2020-02-07 05:37:52

迭代器不需要检测任何并发修改和抛出异常。事实上,在任意并发修改上保证并发修改异常是相当困难的。您永远不应该依赖于抛出此异常。

在您的示例中,如果您希望确保不会发生并发修改,则需要为迭代创建一个entryset的临时副本。要做到这一点,最好的方法是更改行

代码语言:javascript
复制
    for (Map.Entry<String, String> entry : fileMap.entrySet()) {

代码语言:javascript
复制
    for (Map.Entry<String, String> entry : new ArrayList<>(fileMap.entrySet())) {
票数 0
EN

Stack Overflow用户

发布于 2020-02-07 08:18:48

这是在迭代时重命名hashmap中的键的正确方式吗?

将值存储在temp变量中,删除键并将新条目放入新键和temp中

代码语言:javascript
复制
Iterator<Map.Entry<String,String>> iter = fileMap.entrySet().iterator();
while (iter.hasNext()) { 

Map.Entry<String, String> entry = iter.next(); 
fileName = entry.getKey(); 

if (fileName.equals(KEY_REMOVED)) {
fileName = new Timestamp(System.currentTimeMillis()).getTime(); 
String temp = entry.getValue(); 
iter.remove(); 
System.out.println("hashmap after removing key is " + fileMap); 
fileMap.put(fileName, temp); 
System.out.println("Updated hashmap after addng key is " + fileMap); 
} 
else
{
 System.out.println("continue");
}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60103827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档