英文:
Is the hashcode of a Java String created when the String is created, or only at the first call for hashcode?
问题
问题很简单。
字符串的哈希码是何时计算的?
- 当字符串创建时,哈希码也会被计算,并且在构建后始终以O(1)的时间准备好。
- 哈希码仅在第一次调用
hashCode
方法时计算,并在随后的所有调用中以O(1)的时间准备好。 - 每次调用
hashCode
方法时都会计算哈希码。
选项1似乎合理,因为字符串是不可变的。给定字符串的哈希码永远不会更改。但是,这会减慢字符串的创建速度,所以选项2也似乎合理。选项3似乎愚蠢且浪费时间,但可以节省空间,因为哈希码不会被存储。也可能有一些逻辑上的原因,使选项3成为最佳方法,我没有考虑到。
非常感谢您提前的回答。
英文:
My question is quite simple.
When is the hashcode for a String calculated?
- When the String is created, the hashcode is also computed, and always ready in O(1) after construction
- The hashcode is computed only the first time the
hashCode
method is called and is ready in O(1) time for all subsequent calls - The hashcode is computed each time the
hashCode
method is called
Option 1 seems reasonable because Strings are immutable. The hashcode for a given string will never change. But, this slows down the creation of strings, so it also seems reasonable that option 2 would be used. Option 3 seems silly and a waste of time, but saves on space because the hashcode isn't being stored. There may also be some logical reason that Option 3 is the best approach that I'm not thinking about.
Thanks so much in advance
答案1
得分: 3
选项2。第一次调用hashCode
时计算并存储在私有字段中。
在OpenJDK 8中,它看起来像这样:
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;
}
可以在以下链接中找到更多信息:
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java#l1452
事实上,如果查看String类具有哪些字段,您可以看到它有一个名为hash
的私有整数。
System.out.println(String.class.getDeclaredFields());
输出包括:
{ ... private int java.lang.String.hash ... }
英文:
Option 2. It's calculated the first time hashCode
is called and stored in a private field.
In OpenJDK 8 it looks like this:
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;
}
In fact, if you take a look at what fields String has, you can see it has a private int called hash
.
System.out.println(String.class.getDeclaredFields());
output includes
{ ... private int java.lang.String.hash ... }
答案2
得分: 3
From the source code JDK 14:
/** Cache the hash code for the string */
private int hash; // Default to 0
@HotSpotIntrinsicCandidate
public String(String original) {
this.value = original.value;
this.coder = original.coder;
this.hash = original.hash;
}
And then:
public int hashCode() {
// The hash or hashIsZero fields are subject to a benign data race,
// making it crucial to ensure that any observable result of the
// calculation in this method stays correct under any possible read of
// these fields. Necessary restrictions to allow this to be correct
// without explicit memory fences or similar concurrency primitives is
// that we can ever only write to one of these two fields for a given
// String instance, and that the computation is idempotent and derived
// from immutable state
int h = hash;
if (h == 0 && !hashIsZero) {
h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
if (h == 0) {
hashIsZero = true;
} else {
hash = h;
}
}
return h;
}
英文:
From the source code JDK 14
/** Cache the hash code for the string */
private int hash; // Default to 0
@HotSpotIntrinsicCandidate
public String(String original) {
this.value = original.value;
this.coder = original.coder;
this.hash = original.hash;
}
And then
public int hashCode() {
// The hash or hashIsZero fields are subject to a benign data race,
// making it crucial to ensure that any observable result of the
// calculation in this method stays correct under any possible read of
// these fields. Necessary restrictions to allow this to be correct
// without explicit memory fences or similar concurrency primitives is
// that we can ever only write to one of these two fields for a given
// String instance, and that the computation is idempotent and derived
// from immutable state
int h = hash;
if (h == 0 && !hashIsZero) {
h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
if (h == 0) {
hashIsZero = true;
} else {
hash = h;
}
}
return h;
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论