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.)
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..