我在Java映射方面有些挣扎。 我想要一个以byte []作为键并返回自定义对象作为值的映射。
首先,我尝试使用哈希映射,但是因为我曾经使用过不同的数组,但是具有相同的值,所以它不起作用。同样不可能使用Arrays.hashCode(),因为具有不同值的多重数组将具有相同的哈希值。
现在我正在使用TreeMap而不是HashMap进行尝试,但是现在我不知道如何解决
Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
当我尝试添加对象时引发的异常。
有人知道如何解决此异常吗? 或更具体地讲,我应该如何以及向树图提供哪个比较器?
答案 0 :(得分:4)
好,在这里介绍Java。
有两件事在起作用:
因此,以下内容将返回false
:
byte[] a = {1};
byte[] b = {1};
System.out.println(a.equals(b));
Comparable
(对它们而言没有意义)。为了将任何内容放入TreeMap
,您必须为其提供Comparator
(使用this constructor),或者必须实现Comparable
。EDIT :如果您确实有一些要用作键的二进制数据(这很奇怪),您可以:
使用Java NIO的ByteBuffer
及其ByteBuffer.wrap(byte[])
方法(缺点:此类是可变的,但您的原始版本中的byte[]
也是如此)。
在byte[]
上创建一个自定义(最好是不可变的)包装器,并将该类用作HashMap
/ TreeMap
的键(尽管,如果不需要排序, ,出于性能原因,请勿使用TreeMap
。
示例自定义包装的存根:
final class ByteWrapper {
private final byte[] bytes;
public ByteWrapper(byte[] bytes) {
this.bytes = bytes;
}
@Override
public boolean equals(Object o) {
// type checks here
ByteWrapper that = (ByteWrapper) o;
return Arrays.equals(bytes, that.bytes);
}
@Override
public int hashCode() {
return Arrays.hashCode(bytes);
}
}
答案 1 :(得分:2)
原因是您的密钥未实现Comparable
。
一种解决方案是创建一个类(包装器)用作键:
class ByteArrayKey implements Comparable{
byte[] value;
...
}
您所要做的就是根据需要实现compareTo(T o )
(选中Arrays
),当然可以正确使用此实例。
此方法的优点在于,您不必在要使用构造函数实例化的每个TreeMap
中设置Comparator
:
public TreeMap(Comparator<? super K> comparator)
提供更简洁,可维护的代码(如果相等性更改,则只需更改一次)。