使用String(byte[])作为映射的键值

4
我有一个程序,从数据库返回的是byte[]类型的id。我想将这些id(字节数组)用作映射的键。默认情况下,这不起作用,因为比较的是“对象相等性”,而不是“内容相等性”。
接下来我尝试的方法是使用new String(byte[])构造函数实例化一个字符串。虽然这似乎可以工作,但我知道我正在做一些潜在的危险事情。我没有指定编码,这依赖于系统默认值。我也不知道所有的字节序列是否都有在每种编码中的表示。
byte[]转换为String以进行map.put()map.get()操作是安全的吗?我是否考虑到了可能会意外创建冲突的边缘情况(其中具有不同内容的两个不同的byte[]可能成为相同的String)。
注意:该映射存储在内存中,仅在单个应用程序运行期间存在。如果这种方法可行,我写了一个简单的包装类来使我的生活更轻松。
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));
    }
}

这似乎是相关的,可能会有所帮助:https://dev59.com/EWQn5IYBdhLWcg3wa2uV - Chop
2个回答

6

你应该使用BigInteger。它有一个BigInteger(byte[])构造函数,并且具有有效的比较系统。


这似乎非常简单。除非有明显的原因不这样做,否则我会选择这个选项。唯一可能成为问题的是一个带有“前导”零的字节数组,但在我的情况下这不应该是现实。感谢您的答案! - Russ

2

你可以不用直接操作byte[]数组,而是创建一个简单的包装器。

例如:

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

把它作为映射键使用?这比使用内置的String对象更轻量级,并且使键类型变得清晰明了。


嘿,这也可能有效。Arrays.hashCode(prim[])是否基于数组内容产生哈希值? - Russ
那个哈希码和等于方法实际上是由我的IDE生成的。 Arrays.hashcode()保证了两个具有相同哈希码的数组之间调用Arrays.equals()将会评估为真,所以它必须这样做。 - Lyndon Armitage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接