putIfAbsent()不能与ConcurrentHashMap一起使用

时间:2013-10-01 19:55:12

标签: java concurrency hashmap concurrenthashmap

public static void main(String args[]) throws Exception {
    ConcurrentHashMap<byte[], Integer> dps =
         new ConcurrentHashMap<byte[], Integer>();

    System.out.println(dps.putIfAbsent("hi".getBytes(), 1));
    System.out.println(dps.putIfAbsent("hi".getBytes(), 1));
}

打印

null
null

为什么不在第二行打印1?我已经阅读了putIfAbsent的语义,应该保证它能够正常工作。 (注意:这是从大型并发程序中提炼出来的......正如您所看到的,它现在是单线程的。)

1 个答案:

答案 0 :(得分:5)

  

putIfAbsent()不使用ConcurrentHashMap

"hi".getBytes()不是常量数组,因此您在那里生成两个不同的对象。如果您执行了以下操作,则会看到1

byte[] bytes = "hi".getBytes();
System.out.println(dps.putIfAbsent(bytes, 1));
System.out.println(dps.putIfAbsent(bytes, 1));

hashCode()数组上的equals(...)byte[]方法来自Object,它只查看对象的引用,而不是其内容

每当您在Map中存储某些内容时,您需要确保它覆盖hashCode()equals(...)方法,除非您只想比较引用。这是一个Java FAQ。请参阅以下文档:Java theory and practice: Hashing it out

正如@Mauren在评论中提到的那样,要使用byte[]内容,你将不得不写一个包装byte[]的小班并提供正确的{ {1}}和hashCode()方法。或者@CostiCiudatu提及,您可以使用equals(...)并使用SortedMap作为Comparator查看数组内容。

顺便说一句,如果byte[]根据您的字符集等返回使用String.getBytes()类编码的new byte[]