在这段代码中,我已经声明了一个Initialized一个String变量,然后打印了它的hashcode,然后将它重新初始化为另一个值,然后调用垃圾收集器来清除解除引用的对象。
但是当我将String变量重新初始化为其原始值并打印哈希码时,将打印相同的哈希码。怎么样?
x
答案 0 :(得分:3)
散列码与对象相等,而不是身份。
=========== Sheet 1 ===========
location year val1 val2
USA.VT 1999 6 3
USA.VT 2000 3 2
USA.VT 2001 4 1
USA.VT 2002 9 5
USA.NH 1999 3 6
USA.NH 2000 0 0
USA.NH 2001 0 0
USA.NH 2002 12 56
USA.ME 1999 3 16
USA.ME 2000 0 0
USA.ME 2001 0 0
USA.ME 2002 4 5
(如果两种方法一致实施)
即使gc实际发生在这里(并且你并不是简单地引用常量池中的字符串),你也不会期望具有相同字符序列的两个字符串实例不相等 - 因此,它们的哈希码也是一样的。
a.equals(b) implies a.hashCode() == b.hashCode()
答案 1 :(得分:2)
我认为你误解了哈希码的工作方式。在Java中,没有太多细节,哈希码被用于许多事情。一个示例用于查找哈希数据结构中的项目,如HashMap
或HashSet
。
相同值的哈希值应始终返回相同的哈希值。在这种情况下,"JAVA"
的哈希值永远不会改变,因为它会破坏Java中提出的协议。
我认为如何计算String的哈希码是如此复杂。您可以阅读更多相关信息here。我可以举个例子。
假设你有一个班级Fruit
,它有形状,颜色和重量等字段。
您必须为此课程实施equals
和hashcode
。这两者都非常重要,否则你就会破坏Hashmap的工作方式。假设你为hashCode()
方法做了这个。
@Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + this.color;
hash = hash * 31 + this.shape.hashCode();
hash = hash * 31 + this.weight;
return hash;
}
这将为每个相等的Fruit
个实例生成相同的哈希值。这正是你想要的。
真的很快,如何在HashMap
中实际使用它?假设你想看看foo = new Fruit();
HashMap是否首先计算foo.hashCode()
。它会检查存储桶中是否存在该hashCode的任何内容。如果有,那么它将使用equals()
方法,直到它返回true。它必须这样做,因为可能存在哈希码冲突。这就是为什么重要的是为什么equals和hashCode应该一起实现。