在尝试时HashMap
,我发现有些奇怪。
运行4个线程,每个线程尝试使用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");
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
如链接文档中明确指出的那样,它不是线程安全的。您正在提供一个很好的例子说明为什么会这样。是的,您放入重复的密钥是因为put
不检查是否有另一个线程正在放入相同的密钥。这就是说不保证线程安全。
检索行为是不确定的,因此它可以返回此时所需的任何值。它可能非常依赖于实现,平台,甚至与时序有关。
有几种解决方法。在文档中建议的一个是
Map m = Collections.synchronizedMap(new HashMap(...));
另一个选择是使用ConcurrentHashMap
,它是专门为此目的而设计的。
问题内容: 我正在创建一个需要存储键值对的程序。该程序需要接受键形式的请求,并返回相应的值。 问题在于每个键有时有多个值,并且map类不允许重复的键。 这些值是数字,因此无法像使用字符串那样有意义地连接这些值。 对于每个键可以有多个数值的事实,是否有任何优雅的解释方法?我希望返回每个数字,而不是随机返回一个数字。 问题答案: $ cat YourMap.java public class Your
问题内容: 我想要一张包含重复键的地图。 我知道有很多地图实现(Eclipse向我展示了大约50个),所以我敢肯定一定有一个允许这样做的地图实现。我知道编写自己的地图很容易做到这一点,但是我宁愿使用一些现有的解决方案。 也许在Commons Collections或Google Collections中? 问题答案: 你正在搜索多图,而commons-collection和Guava确实都有几种实
在Java集合中,哪个集合不允许重复,哪个集合还保留数据的插入顺序?
问题内容: 这个问题已经在这里有了答案 : “ INSERT IGNORE”与“ INSERT…ON DUPLICATE KEY UPDATE” (11个答案) 6年前关闭。 我正在尝试完成此查询;我的标签字段设置为UNIQUE,我只是希望数据库忽略任何重复的标签。 甚至可以接受 问题答案: 建议不要使用INSERT IGNORE,因为它会忽略所有错误(即,草率的全局忽略)。相反,由于在您的示例中
问题内容: 因此,我对以下方面的理解: 当然,问题在于,如果存在多个具有相同值的s,则它们会折叠在一起,最后一个以那个唯一的唯一成员存在。我实际上想将结果字典的值列出: 这种理解是否可能? 问题答案: 您可以将元素一一添加到默认情况下包含空列表的字典中: 您也可以执行非常相似的操作,而不必使用collections模块: 但这可以说是不太清晰。 一个等效的,更清晰的(不需要“解析”不太常见的)
问题内容: 我想我可能已经发现Java错误。 我有一个TreeMap,其中使用了自定义比较器。但是,似乎当我将(key,value)放在已经存在的键上时,它不会覆盖该键,从而创建了重复的键。我想我已经验证了这一点,因为我尝试过 这打印出真实的。有人知道为什么会这样吗? 这是比较器代码: 问题答案: 比较器始终需要返回一致的结果,并且在TreeMap中使用时,应与equals保持一致。 在这种情况下