Ответ 1
С# имеет встроенные типы значений, которые обеспечивают равенство значений, в то время как Java не делает. Поэтому писать собственный хэш-код в Java может быть необходимостью, тогда как выполнение этого в С# может быть преждевременной оптимизацией.
Общепринято писать тип для использования в качестве составного ключа для использования в словаре /HashMap. Часто для таких типов вам нужно равенство значений (эквивалентность) в отличие от ссылочного равенства (идентификация), например:
IDictionary<Person, IList<Movie> > moviesByActor; // e.g. initialised from DB
// elsewhere...
Person p = new Person("Chuck", "Norris");
IList<Movie> chuckNorrisMovies = moviesByActor[p];
Здесь, если мне нужно создать новый экземпляр Person для выполнения поиска, мне нужно Person
реализовать значение равенства, иначе оно не будет соответствовать существующим записям в словаре, поскольку они имеют различную идентификацию.
Чтобы получить равенство значений, вам необходимо переопределить Equals()
и GetHashCode()
на обоих языках.
С# structs (типы значений) реализовать равенство ценности для вас (хотя и потенциально неэффективное) и обеспечить последовательную реализацию GetHashCode
. Этого может быть достаточно для многих людей, и они не пойдут дальше, чтобы реализовать свою собственную улучшенную версию, если проблемы с производительностью не диктуют иначе.
В Java нет такой встроенной функции языка. Если вы хотите создать тип с семантикой равенства значений для использования в качестве составного ключа, вы должны реализовать equals() и соответственно hashCode() самостоятельно. (Есть сторонние помощники и библиотеки, которые помогут вам сделать это, но ничего не встроено в язык).
Я описал типы значений С# как "потенциально неэффективные" для использования в словаре, потому что:
- Сама реализация
ValueType.Equals
может быть медленной. Это используется в поиске словаря. - Реализация
ValueType.GetHashCode
, хотя и правильная, может привести к множеству столкновений, что также приведет к очень плохому результату работы с словарем. Взгляните на этот ответ на вопрос Q от Jon Skeet, в котором показано, чтоKeyValuePair<ushort, uint>
, похоже, всегда дает тот же hashCode!