5

当我说Java时。

String str= "abcd";
str.hashCode(); 

我的问题是哈希码是什么时候计算的?@ 第 1 行还是 @ 第 2 行?

我假设,哈希码是预先计算的。每当更新字符串时,哈希码也会“可能”更新。

或者它的另一种方式,即每次调用java 时都会使用此处str.hashCode()描述的公式计算它。

Java 字符串上 hashCode() 的一致性

4

6 回答 6

9

字符串无法更新,因为它们是不可变的,并且值在计算一次后被缓存:

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
于 2013-07-10T11:39:11.377 回答
1

String.hashCode() 方法仅在您调用它时被触发,就像您在 Java 中编写或使用的任何其他方法一样。

因此,要回答您的问题,创建字符串时不会计算哈希码。

如果你看到 hashcode 方法,它只计算一次并将预先计算的 hashcode 值保存到局部变量 hash

public int hashCode() {
 int h = hash;
 if (h == 0) {
  int off = offset;
  char val[] = value;
  int len = count;
  for (int i = 0; i < len; i++) {
   h = 31*h + val[off++];
  }
  hash = h;
}
return h;
} 

因此,只有在调用该方法时才会计算哈希码

于 2013-07-10T12:19:30.543 回答
1

您不能“更新”字符串。字符串是不可变的。当你“改变”一个字符串实例时,你实际上得到了一个新的字符串实例。

于 2013-07-10T11:37:42.217 回答
1

您无法更新现有String实例,因为String 是 immutable。您将能够做的是创建一个新实例并将其分配给相同的变量。

于 2013-07-10T11:46:13.273 回答
0

对于大多数字符串,哈希值将在第一次hashCode()被调用时计算,或者——在多线程场景中——每次调用它,直到其中一个调用设法计算并缓存它的值。但是,包含哈希码计算为零的字符序列的字符串实例将在每次hashCode()调用它们时计算其哈希值。请注意,可以通过使用一个哈希函数来避免这种冗余计算,该函数对于非平凡的字符串永远不会返回零(例如,通过添加 line if (!h) h=value.length+1;),但是现在改变 Java 来做到这一点可能 - 至少在理论上--break 一些现有代码,假设内置字符串hashCode()曾经产生零的任何字符序列将继续这样做,直到时间结束。

因为写入一个类型的变量String只会覆盖包含的引用,而不会影响String它之前引用的实例,所以与之前字符串的哈希码相关的任何内容(包括它的值是否尚未计算)都不会受到影响任务。

于 2013-07-12T15:58:56.603 回答
0

我看到这个问题仍然“没有回答”。通过谷歌搜索找到它。因此,总结所有答案并添加更多价值:

  • 字符串的 hashCode 在第一次调用此函数时被缓存,有一个内部字段 hashCode 初始化为零
  • 字符串是不可变的,但您可以使用反射 API 更改它们。缓存的 hashCode 仍然不会自动更新
  • 由字符常量初始化的字符串总是被保留的,所以如果你写

    public static void main(String[] args) {
        String hello1 = "Hello";
        String hello2 = "Hello";
        System.out.println( hello1 == hello2 );
    }
    

您可以确定它会打印出“true”。如果您调用 hello1 和 hello2 的 hashCode,则 hashCode 将只计算一次,因为它实际上是同一个对象。

希望这些信息对那些通过谷歌搜索到达那里的人有用。

于 2016-06-29T18:47:47.373 回答