HashMap持有重复键 [英] HashMap holding duplicate keys

查看:212
本文介绍了HashMap持有重复键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用 HashMap 时,我注意到一些奇怪的现象。



键,值),键值从0到9999,值为一个常量字符串。完成所有线程后, map.size()返回的值大于10,000。这怎么发生的?这是否意味着该映射包含重复键?



我在 map.entrySet()上迭代并发现某些键的计数确实大于1.如果我在地图上对一个这样的键执行 get(),将返回什么值。



这是我试过的代码

  final HashMap< String ,String> vals = new HashMap<>(16_383); 
Runnable task = new Runnable(){
@Override
public void run(){
for(int i = 0; i< 10000; i ++){
vals.put(+ i,Thread.currentThread()。getName());
}
}
};
Thread thread = new Thread(task,a);
线程thread1 =新的线程(任务,b);
线程thread2 =新线程(任务,c);
Thread thread3 = new Thread(task,d);
thread.start();
thread1.start();
thread2.start();
thread3.start();
thread.join();
thread1.join();
thread2.join();
thread3.join();
System.out.println(Thread.currentThread()。getName()+vals+ vals.size());
System.out.println(Thread.currentThread()。getName()+vals+ vals.entrySet()。size());
System.out.println(Thread.currentThread()。getName()+vals+ vals.keySet()。size());


解决方案

HashMap 不是线程安全的,因为在链接的文档中明确指出。你提供了一个很好的例子,说明这是为什么。是的,因为 put 不检查另一个线程是否放入了相同的密钥,所以放入了重复的密钥。这就是说不是线程安全的。



检索行为是未定义的,所以它可以返回当前想要的值。这可能是非常实现的,平台的,甚至是依赖于时序的。

有几个解决方法。在文档中建议的是

lockquote

Map m = Collections.synchronizedMap(new HashMap(...)) ;


另一种选择是使用 ConcurrentHashMap ,它明确地为目的。

While experimenting with HashMap, I noticed something weird.

Ran 4 threads with each trying to put (key,value) with keys from 0 to 9999, value a constant string. After all threads were done, map.size() returned a value greater than 10,000. How did this happen? Does this mean that the map contains duplicate keys?

I iterated on the map.entrySet() and found that the count for some keys were indeed more than 1. What value would be returned if I do a get() on the map for one such key.

Here is the code that I tried

final HashMap<String, String> vals = new HashMap<>(16_383);
Runnable task = new Runnable() {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            vals.put(""+i, Thread.currentThread().getName());
        }
    }
};
Thread thread = new Thread(task, "a");
Thread thread1 = new Thread(task, "b");
Thread thread2 = new Thread(task, "c");
Thread thread3 = new Thread(task, "d");
thread.start();
thread1.start();
thread2.start();
thread3.start();
thread.join();
thread1.join();
thread2.join();
thread3.join();
System.out.println(Thread.currentThread().getName() + "vals "+ vals.size());
System.out.println(Thread.currentThread().getName() + "vals "+ vals.entrySet().size());
System.out.println(Thread.currentThread().getName() + "vals "+ vals.keySet().size());

解决方案

HashMap is not thread safe, as explicitly noted in the linked docs. You are providing a good example of why this is so. Yes, you are putting in duplicate keys because put does not check that another thread is putting the same key in. That is what it means not to be thread safe.

The retrieval behavior is undefined, so it can return whichever value it wants at that point. It is probably very implementation, platform and even timing-dependent.

There are a couple of workarounds. The one suggested in the docs is

Map m = Collections.synchronizedMap(new HashMap(...));

Another option is to use ConcurrentHashMap, which is explicitly designed for the purpose.

这篇关于HashMap持有重复键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆