Создается ли хэш-код строки Java при создании строки или только при первом вызове хэш-кода? - PullRequest
1 голос
/ 03 августа 2020

Мой вопрос довольно прост.

Когда вычисляется хэш-код для String?

  1. Когда создается String, хэш-код также вычисляется и всегда готов в O (1) после построения
  2. Хэш-код вычисляется только при первом вызове метода hashCode и готов за O (1) раз для всех последующих вызовов
  3. Хэш-код вычисляется каждый когда вызывается метод hashCode,

Вариант 1 кажется разумным, потому что строки неизменяемы. Хэш-код для данной строки никогда не изменится. Но это замедляет создание строк, поэтому также кажется разумным использовать вариант 2. Вариант 3 кажется глупым и пустой тратой времени, но экономит место, потому что хэш-код не сохраняется. Также может быть какая-то логическая причина, по которой вариант 3 - лучший подход, о котором я не думаю.

Заранее большое спасибо

Ответы [ 2 ]

3 голосов
/ 03 августа 2020

Из исходников 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;
    }

А потом

    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;
    }
3 голосов
/ 03 августа 2020

Вариант 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, вы увидите, что у него есть частный int с именем hash.

System.out.println(String.class.getDeclaredFields());

вывод включает

{ ... private int java.lang.String.hash ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...