Russ
Russ

Reputation: 2006

Using String(byte[]) as key to map

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

Upvotes: 4

Views: 878

Answers (2)

Lyndon Armitage
Lyndon Armitage

Reputation: 452

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.

Upvotes: 2

OldCurmudgeon
OldCurmudgeon

Reputation: 65793

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

Upvotes: 6

Related Questions