Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using String(byte[]) as key to map

Tags:

java

I have a program that gets ids from a database returned as a byte[]. I want to use those ids (byte arrays) as keys to a map. By default this does not work because what is compared is "object equality" not "content equality".

The next thing I tried which seemed to work is instantiating a String with the new String(byte[]) constructor. While this seems to work I know I'm doing some potentially dodgy things. I am not specifying an encoding which relies on whatever the system default is. I also don't know if all byte sequences will have representation in every encoding.

Is "converting" byte[] to String for the purpose of doing a map.put() and map.get() safe? Are there edge cases I'm not considering where this approach would inadvertently create a collision (where 2 different byte[]'s with different content could become the same String).

Note: The map is stored in memory and only lives for a single application run. Simple wrapper class I wrote to make my life easier if this approach is viable:

public class Cache {

    Map<String, Set<String>> cache = new HashMap<String, Set<String>>();

    public Cache() {}

    public void put(byte[] key, Set<String> value) {
        cache.put(new String(key), value);
    }

    public Set<String> get(byte[] key) {
        return cache.get(new String(key));
    }
}
like image 999
Russ Avatar asked Feb 09 '23 10:02

Russ


2 Answers

You should probably use Biginteger. It has a BigInteger(byte[]) constructor and has an effective comparison system.

like image 172
OldCurmudgeon Avatar answered Feb 22 '23 05:02

OldCurmudgeon


Could you not build a simple wrapper around your byte[] array instead?

Something akin to:

public class CacheKey {
    private final byte[] key;

    public CacheKey(byte[] key) {
        this.key = key; // You may want to do a defensive copy here
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        CacheKey cacheKey = (CacheKey) o;
        return Arrays.equals(key, cacheKey.key);
    }

    @Override
    public int hashCode() {
        return key != null ? Arrays.hashCode(key) : 0;
    }
}

And use that as the map key? It would be a little more lightweight than using the built in String object and makes the key type actually clear.

like image 32
Lyndon Armitage Avatar answered Feb 22 '23 05:02

Lyndon Armitage