How to use byte arrays as keys in MapDB

1.4k Views Asked by At

I have a use case where I'd like to use opaque byte[] as keys into a MapDb. I discovered this - Using a byte array as Map key - limitation quickly; and wonder which approach is recommended.

I'd rather not create a bunch of interim objects and serialization overhead, but it seems like ByteBuffer.wrap(my_bytes) is where Java is pointing me.

I'm hoping one of the core devs of MapDB can weigh in on this or a ByteBuffer JVM guru.

2

There are 2 best solutions below

1
On BEST ANSWER

MapDB author here.

It is possible to use byte[] without wrappers. There is Hasher which handles hashCode and equals methods for HTreeMap:

    Map map = db.createHashMap("map")
            .hasher(Hasher.BYTE_ARRAY)
            .keySerializer(Serializer.BYTE_ARRAY)
            .makeOrGet();
1
On

Actually, I can't see anything wrong in the approach suggested in the linked answer. They say you have to wrap your byte array into some class having predictable and consistent hashCode() and equals() implementations. Someone suggests using String or ByteBuffer, but that would definitely be a hack and may screw up at some point. This simple wrapper may be enough (note that I made a defensive copy of the input bytes to prevent modifications that will alter hashCode() and equals() computations: key in maps must be immutable):

class HashtableByteArray {

  private final byte[] data;

  public HashtableByteArray(byte[] data) {
    this.data = Arrays.copyOf(data, data.length);
  }

  public int hashCode() {
    return Arrays.hashCode(data);
  }

  public boolean equals(Object other) {
    return other instanceof HashtableByteArray
      && Arrays.equals(data, ((HashtableByteArray) other).data);
  }
}

This sample relies heavily on the utils in the Arrays class, but you can certainly build your version with optimized hashCode() and equals() that better suite your needs.