如果我们有如下课程:
class ConnectedPair {
private String source;
private String destination;
public ConnectedPair(String source, String destination) {
if(source == null || destination == null) {
throw new NullPointerException();
}
this.source = source;
this.destination = destination;
}
}
我们想把它用在 HashMap
或者 HashSet
我们需要实施 equals
以及 hashCode
自动生成的 hashCode
本课程的目标是:
@Override
public int hashCode() {
int result = source.hashCode();
result = 31 * result + destination.hashCode();
return result;
}
但我想知道我们是否应该做以下几点:
@Override
public int hashCode() {
return (source + "=>" + destination).hashCode();
}
这比自动生成的方法好还是坏?正如我所看到的,其他脚本语言也在使用类似的方法,我想知道生成的哈希是更好还是更差(或者没有区别)。
注意:我们忽略字符串concat作为性能的缺点,假设它可以被缓存并因此得到优化
1条答案
按热度按时间rxztt3cl1#
如果您所关心的只是一个有效的实现,并且对于意外和/或故意碰撞的可能性没有具体的要求,那么它们都是好的。这是大多数案件:你可以在这里停止调查。
这两个问题的定义都相当糟糕
String.hashCode()
. 因为历史原因String.hashCode()
对它的工作方式有一个固定的定义,这个定义是。。。糟糕。它很容易发生意外碰撞,并且很容易构造有意碰撞。第二个(字符串连接)使得构造两个非常简单
ConnectedPair
具有相同哈希代码的对象(new ConnectedPair("a=>b", "c").hashCode() == new ConnectedPair("a","b=>c").hashCode()
). 另一个选项并不能完全阻止这一点,但会使构造样本稍微困难一些。这听起来可能很愚蠢,但生成的代码是惯用的:每个看到这段代码的java开发人员都会很快理解您在做什么。您的“定制”实现似乎没有明显的问题,但是需要稍微多一些的脑力来解析。请记住:阅读代码的频率要比编写代码的频率高得多。