Using a byte array as Map key
It's okay so long as you only want reference equality for your key - arrays don't implement "value equality" in the way that you'd probably want. For example:
byte[] array1 = new byte[1];byte[] array2 = new byte[1];System.out.println(array1.equals(array2));System.out.println(array1.hashCode());System.out.println(array2.hashCode());
prints something like:
false167171111394033
(The actual numbers are irrelevant; the fact that they're different is important.)
Assuming you actually want equality, I suggest you create your own wrapper which contains a byte[]
and implements equality and hash code generation appropriately:
public final class ByteArrayWrapper{ private final byte[] data; public ByteArrayWrapper(byte[] data) { if (data == null) { throw new NullPointerException(); } this.data = data; } @Override public boolean equals(Object other) { if (!(other instanceof ByteArrayWrapper)) { return false; } return Arrays.equals(data, ((ByteArrayWrapper)other).data); } @Override public int hashCode() { return Arrays.hashCode(data); }}
Note that if you change the values within the byte array after using the ByteArrayWrapper
, as a key in a HashMap
(etc) you'll have problems looking up the key again... you could take a copy of the data in the ByteArrayWrapper
constructor if you want, but obviously that will be a waste of performance if you know you won't be changing the contents of the byte array.
EDIT: As mentioned in the comments, you could also use ByteBuffer
for this (in particular, its ByteBuffer#wrap(byte[])
method). I don't know whether it's really the right thing, given all the extra abilities that ByteBuffer
s have which you don't need, but it's an option.
The problem is that byte[]
uses object identity for equals
and hashCode
, so that
byte[] b1 = {1, 2, 3}byte[] b2 = {1, 2, 3}
will not match in a HashMap
. I see three options:
- Wrapping in a
String
, but then you have to be careful about encoding issues (you need to make certain that the byte -> String -> byte gives you the same bytes). - Use
List<Byte>
(can be expensive in memory). - Do your own wrapping class, writing
hashCode
andequals
to use the contents of the byte array.
We can use ByteBuffer for this (This is basically the byte[] wrapper with a comparator)
HashMap<ByteBuffer, byte[]> kvs = new HashMap<ByteBuffer, byte[]>();byte[] k1 = new byte[]{1,2 ,3};byte[] k2 = new byte[]{1,2 ,3};byte[] val = new byte[]{12,23,43,4};kvs.put(ByteBuffer.wrap(k1), val);System.out.println(kvs.containsKey(ByteBuffer.wrap(k2)));
will print
true