Java 使用具有两个泛型字段的类重写哈希代码
我正在实现一个类Java 使用具有两个泛型字段的类重写哈希代码,java,hashmap,hashcode,keyvaluepair,Java,Hashmap,Hashcode,Keyvaluepair,我正在实现一个类对,将其用作一个具有两个值的键,用于HashMap。我使用泛型来保持字段变量的类型。我成功地编写了代码的最大部分: public class Pair<L, R> { private L left; private R right; Pair(L left, R right) { this.left = left; this.right = right; } public L ge
对
,将其用作一个具有两个值的键,用于HashMap
。我使用泛型来保持字段变量的类型。我成功地编写了代码的最大部分:
public class Pair<L, R>
{
private L left;
private R right;
Pair(L left, R right)
{
this.left = left;
this.right = right;
}
public L getLeft()
{
return left;
}
public R getRight()
{
return right;
}
public void setLeft(L left)
{
this.left = left;
}
public void setRight(R right)
{
this.right = right;
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof Pair< ? , ? >)
{
Pair< ? , ? > pair = (Pair< ? , ? >)obj;
return left.equals(pair.getLeft()) && right.equals(pair.getRight());
}
return false;
}
@Override
public String toString()
{
return "Pair " + Integer.toHexString(hashCode()) + ": (" + left.toString() + ", " + right.toString()
+ ")";
}
}
公共类对
{
列兵L左;
私权;
成对(左左,右)
{
this.left=左;
这个。右=右;
}
公共L getLeft()
{
左转;
}
公共权利
{
返还权;
}
公共无效设置左(左)
{
this.left=左;
}
公共无效设定权(右)
{
这个。右=右;
}
@凌驾
公共布尔等于(对象obj)
{
if(对的obj实例<?,?>)
{
配对<?,?>配对=(配对<?,?>)obj;
返回left.equals(pair.getLeft())和&right.equals(pair.getRight());
}
返回false;
}
@凌驾
公共字符串toString()
{
返回“Pair”+Integer.toHexString(hashCode())+”:(“+left.toString()+”,“+right.toString())
+ ")";
}
}
我的问题是创建适当的hashCode
方法,它为相同的对象提供相同的hashCode,为不同的对象提供不同的hashCode。一些提示?这应该可以做到(当然,哈希代码永远不能保证是不同的)
如果left或right可以为null,您需要更多的代码来处理它。不要重新发明轮子
只需使用您已经在依赖左
和右equals
方法,那么为什么不也依赖它们的hashcode
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (left ==null? 0 : left.hashCode());
result = prime * result + (right ==null? 0 : right.hashCode());
return result;
}
相等的对象应该有相同的散列码,但两个不相等的对象不一定有不同的散列码(tho,它们应该经常不同)。这是使用justreturn objects.hash(左、右)时免费获得的代码>至少Oracle的Java 7实现正好使用了这一点。但是,使用JRE方法允许将来的改进…@Holger是的,感谢您指出,我不知道该方法(仍在JDK 6上),但是,它看起来像对象。hash()
会导致额外的数组创建,这在本例中可能无关紧要,但值得考虑。好建议,我也想过使用左右哈希代码,但不知道如何以最佳方式使用它们。无论如何,我最好还是坚持使用本机java实现。这正是我一直在寻找的!它对Java1.7真的很有帮助。但是,您可能会注意到,对于Java1.6及更低版本,我们应该选择什么?@Puzzle:复制即可。它非常简单,可以与1.6甚至1.5一起使用…@Holger:是什么让你认为left.hashCode()-right.hashCode()
提供了更好的结果?不难想象,left.hashCode()-right.hashCode()
是个坏主意。。。例如,Integer
类将值作为hashCode返回;因此,如果您使用这个泛型类来创建整数对,那么创建哈希冲突就非常容易(在正常使用情况下也很有可能)。hashCode
针对任意字符串进行了优化,最好是人类可读的文本。它没有针对字符串进行优化,在65536个可能的字符中最多使用12个不同的字符。仅仅因为很难看到缺陷并不意味着这是一个更好的解决方案。您的解决方案只是隐藏正在发生的事情。我不认为String.hashCode对字符串的内容做出任何假设。请看,做出任何假设的不是方法String.hashCode
,而是用来证明结果足够的一组测试用例,这会产生不同。“使用31”理念的最初发明者(我想没有人知道谁是第一个)不需要知道它为什么会起作用。尽管如此,通过对int
表示的String
逐字符散列来对int
进行散列仍然使用了一种专为文本设计的算法,这正是由于“逐字符”的性质,独立于所使用的31
number.String.hashCode可能是hashCode()最重要的实现在整个Java世界。我相信它在中文文本上的效果和在只包含“0”和“1”的字符串上的效果一样好,因为有太多不同的程序依赖它。因此,我的建议的不足可能是构建字符串所需的开销,但如果它是string.hashCode(),我将被诅咒。
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (left ==null? 0 : left.hashCode());
result = prime * result + (right ==null? 0 : right.hashCode());
return result;
}