Какой хороший рецепт для переопределения hashcode в Dart?
Я нахожусь в том, что хочу переопределить hashcode и == для объекта, и мне интересно, есть ли лучшие методы для реализации хэш-кода, который зависит от нескольких атрибутов, и кажется, что есть некоторые особенности, связанные с Дартом.
Простейшим ответом будет XOR хэши всех атрибутов вместе, и это, вероятно, не так уж плохо. Также есть пример в Dart Up и Running at https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html
// Override hashCode using strategy from Effective Java, Chapter 11.
int get hashCode {
int result = 17;
result = 37 * result + firstName.hashCode;
result = 37 * result + lastName.hashCode;
return result;
}
но похоже, что он ожидает усечения целочисленной семантики и в Dart, переполняющем диапазон JS-целых чисел, кажется плохой для хэширования.
Мы могли бы это сделать и просто усекать до 32 бит после каждой операции.
Для моего приложения ожидаемый размер набора очень мал и почти ничего не будет, но я удивлен, что не вижу стандартный рецепт для общего случая. Кто-нибудь имеет опыт или сильный опыт в этом?
Ответы
Ответ 1
колчан пакет предоставляет вспомогательные функции hash2
, hash3
и т.д., которые упрощают задачу реализации hashCode
, с некоторой уверенностью, что он работает правильно под Dart VM и при компиляции на JavaScript.
import 'package:quiver/core.dart';
class Person {
String name;
int age;
Person(this.name, this.age);
bool operator ==(o) => o is Person && name == o.name && age == o.age;
int get hashCode => hash2(name.hashCode, age.hashCode);
}
Также см. этот пост для обсуждения немного длиннее.
Ответ 2
Так как Dart настолько похож на Java, вы наверняка найдете хорошие ссылки на hashCodes для Java, которые применимы и для Dart.
Маленький поисковик взял меня на страницу Wikipedia на Java Object.hashCode()
. Имеет очень простой пример для хэш-кода простого объекта. Популярной методологией является выполнение умножения с простым числом (разные) и добавление некоторого значения для каждого свойства объекта.
Этот вопрос f.e. объясняет, почему число 31 выбрано для умножения для метода String.hashCode()
.
Более подробные примеры реализации хэш-кода можно легко найти с помощью Google.
Ответ 3
В то время как это не очень хороший ответ, есть открытая ошибка для обеспечения этого в https://code.google.com/p/dart/issues/detail?id=11617 и "хэши Jenkins SMI", на которые они ссылаются похоже, было бы лучше всего использовать, если бы оно было общедоступным.