Использование чисел при переопределении метода hashCode

1,00
р.
Да, в гугле можно найти статью Разбираемся с hashCode() и equals(), где вполне доступным языком описаны правила переопределения hashCode() и equals(). В крайнем случае можно взять того же Блоха с его Философией Java и посмотреть там эти правила. Речь не об этом. Правила мне понятны.
Непонятно вот что:
@Override public int hashCode() { int hash = 37 hash = hash * 17 + str1.hashCode() hash = hash * 17 + str2.hashCode() hash = hash * 17 + num return hash }
В разных примерах за основу берут какие-то числа. В данном примере взяты 37 и 17. Таких примеров в Интернете масса, но в каждом из них числа разные. В одном примере вообще встретилась такая конструкция:
@Override public int hashCode() { int hash = new Random().nextInt(255) hash = hash * 255 + dozer.hashCode() hash = hash * 255 + tank.hashCode() return hash }
Что окончательно сбило меня с толку. Как всё же правильно переопределять хеш-код?
В связи с этим ряд вопросов:
Нужно ли вообще использовать какие-то числа? Есть ли разница какое число выбирать? Или это некая "договорённость" внутри команды при разработке продукта? Существуют ли ограничения на выбор стартового числа? Почему каждый раз хеш нужно умножать сам на себя (прибавление хешей полей объекта мне понятно)?

Ответ
Почему используется 37 и 17 ? Как правило, в качестве начального значения выбирается простое число, это сделано для уменьшения вероятности возникновения коллизии. Смысл какое число выбирать, конечно, имеет. Если вы будете хранить ваши объекты в хэш таблице, то ее производительность прямо зависит от реализации hashCode() см. пункт 1 Для того, чтобы значения хэша были максимально отличны для объектов имеющих одинаковые значения полей. Этим мы добиваемся равномерного распредления ключей, в хэш таблице.