Question

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));
}

prints

null
null

Why doesn't it print a 1 on the second line? I have read the semantics for putIfAbsent and it should be guaranteed to work. (Note: this was distilled down from a large concurrent program... as you can see, it's now single-threaded.)

Was it helpful?

Solution

putIfAbsent() not working with ConcurrentHashMap

"hi".getBytes() is not a constant array so you are generating two different objects there. If you did something like the following you will see your 1.

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

The hashCode() and equals(...) methods on byte[] array are from Object which only looks at the reference of the object, not its contents.

Whenever you store something in a Map you need to make sure it overrides hashCode() and equals(...) methods unless you want to just compare references. This is a Java FAQ. See these docs: Java theory and practice: Hashing it out.

As @Mauren mentions in the comments, to use the contents of byte[] you are going to have to write a little class which wraps the byte[] and provides proper hashCode() and equals(...) methods. Or as @CostiCiudatu mentions, you can use a SortedMap and use a Comparator for byte[] which looks at the contents of the array.

As an aside, if String.getBytes() returns a new byte[] encoded with the StringCoding.StringEncoder class based on your character set, etc..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top