开发者

Is Java String really immutable?

In String source it looks like the hash code value (private int hashCode) is set only if the method public int hashCode() was called at least once. That means a different state. But will the 开发者_开发知识库hashCode be set in the following example:

String s = "ABC"; ? 

Will

String s = "ABC"; 
s.hashCode();

help with subsequent comparisons performance?


Immutable means that, from an outside perspective, the value of the object cannot be changed.

If hashCode is being cached, the internal state of the object may be different after the first hashCode call. But that call is read-only, and you can't change the value of the object as it appears to the outside world.

In other words, it's still the same string.


Technically the string has changed. Some internal field is altered the first time you call hashCode().

But for all practical reasons the string is immutable. The value of the hash code doesn't change due to a call to hashCode(), it simply isn't calculated until the first call. To any consumer of a string, the string is immutable. And that's what matters.


As also stated by Robert Harvey and Greg, for all practical purposes, String object is immutable (it might be possible to change the contents with reflection but that is a hack).

Calling hashCode() immediately after construction might help with performance IN THEORY. However, for all practical purposes, this is premature optimization.


But will the hashCode be set in the following example?

No.

Will [calling hashCode] help with subsequent comparisons performance?

Assuming that you mean subsequent calls to String.equals(Object), the answer is "No". The equals method does not use a String's hash value, whether or not it has previously been calculated.

If you are referring to calls to String.hashCode(), the answer is "Probably Not". At most you are getting a one-time calculation to happen sooner rather than later. The hashCode method still needs to test if hash is zero on every call.

EDIT

I think it is clear that different JVM vendors implement String.equals differently. For example, the IBM version cited by @Alex uses the cached hashcode, but the version in Sun's JDK 1.6 does not.

From this we conclude that any attempt to call String.hashCode() in order to "optimize" String.equals is going to have results that depend on the JVM. Furthermore, for the particular IBM JVM that @Alex is using, it looks like it could be beneficial ... provided that you've done it for both strings.

But I still think this is a bad idea ... unless you've got clear evidence from profiling that String.equals() is a significant bottleneck.


  1. No. Nobody calls it so it isn't called.

  2. No. How could calling a method an extra time make anything faster?


This is the actual String.hashCode() implementation:

public int hashCode() {
int h = hash;    // hash is a field in String
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;
}

So:

  1. Strings are immutable, you can not change it's value. You can only create a new String.
  2. String hashcode gets calculated on first use of String.hashCode(). Later invocations return precalculayed value:
  3. YES, it will be faster. If you call .hashCode() then subsequent comparisons will be faster for a tiny amount of time of one-time calculating hachcode. The question is if this is substantial. Do your own benchmark.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜