Подтвердить что ты не робот

Использовать Objects.hash() или собственную реализацию hashCode()?

Недавно я обнаружил метод Objects.hash().

Моя первая мысль заключалась в том, что это значительно облегчает реализацию hashCode(). См. Следующий пример:

@Override
//traditional
public int hashCode() {
    int hash = 5;
    hash = 67 * hash + (int)(this.id ^ (this.id >>> 32));
    hash = 67 * hash + (int)(this.timestamp ^ (this.timestamp >>> 32));
    hash = 67 * hash + Objects.hashCode(this.severity);
    hash = 67 * hash + Objects.hashCode(this.thread);
    hash = 67 * hash + Objects.hashCode(this.classPath);
    hash = 67 * hash + Objects.hashCode(this.message);
    return hash;
}

@Override
//lazy
public int hashCode() {
    return Objects.hash(id, timestamp, severity, thread, classPath, message);
}

Хотя я должен сказать, что это кажется слишком хорошим, чтобы быть правдой. Также я никогда не видел этого использования.

Есть ли недостатки использования Objects.hash() по сравнению с реализацией собственного хеш-кода? Когда я буду выбирать каждый из этих подходов?

Обновление

Несмотря на то, что эта тема отмечена как разрешенная, не стесняйтесь оставлять ответы на вопросы, которые предоставляют новую информацию и проблемы.

4b9b3361

Ответ 1

Обратите внимание, что параметр Objects.hash равен Object.... Это имеет два основных последствия:

  • Примитивные значения, используемые в вычислении хэш-кода, должны быть помещены в бокс, например. this.id преобразуется из long в long.
  • Для вызова метода должен быть создан Object[].

Стоимость создания этих "ненужных" объектов может складываться, если часто вызывается hashCode.

Ответ 2

Ниже приведена реализация Objects.hash - которая внутренне вызывает Arrays.hashCode.

public static int hash(Object... values) {
    return Arrays.hashCode(values);
}

Это реализация метода Arrays.hashCode

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}

Итак, я согласен с @Andy Стоимость создания этих "ненужных" объектов может складываться при частом вызове hashCode. Если вы реализуете себя, это будет быстрее.

Ответ 3

Я хотел бы попытаться сделать сильный аргумент для обоих.

Объявление об отказе от открытия

Для этого ответа Objects.hash(), Objects.hashCode() и любая функция, предоставляемая любой библиотекой, выполняющей эту роль, взаимозаменяемы. Во-первых, я хотел бы утверждать, используйте Objects.hash() или вообще не использую функции статических объектов. Любой аргумент для или против этого метода требует принятия предположений о скомпилированном коде, который не гарантируется как истинный. (Например, оптимизатор компилятора может преобразовать вызов функции в встроенный вызов, тем самым минуя дополнительный стек вызовов и распределение объектов. Подобно тому, как циклы, которые ничего полезного не делают, не переходят к скомпилированной версии (если вы не отключите оптимизатор). У вас также нет гарантии, что будущие версии Java не будут включать версию JVM, например, С# в этой версии этого метода (по соображениям безопасности, я считаю)). Таким образом, единственный безопасный аргумент, который вы можете сделать относительно использования этой функции, заключается в том, что в целом безопаснее оставлять детали правильного хэша для этой функции, чем пытаться реализовать свою собственную наивную версию.

Для объекта Objects.hash

  • Гарантируется хороший хеш.
  • Выполняется 5 секунд.
  • У вас была бы ошибка в нем (как-то особенно, если вы скопировали реализацию)

Против Objects.hash

  • Java docs не делает promises о кросс-совместимости хэша (будут ли JVM v6 и JVM v8 давать одинаковые значения "всегда" через ОС?)
  • Что касается hashCodes, они лучше всего работают, если "равномерно распределены". Поэтому, если значение int действует только для диапазонов от 1 до 100, вы можете захотеть "перераспределить" свои хэш-коды, чтобы не все были частью одного и того же ведра.
  • Если у вас есть какие-либо требования, которые заставляют вас задаться вопросом о том, как работает Objects.hash, надежность/производительность, подумайте внимательно, если хэш-код действительно то, что вы хотите, и реализуйте собственный метод хэш-кодирования, который адресует ваш.