Boolean.hashCode ()


122

hashCode()Метод класу Boolean реалізується в такий спосіб:

public int hashCode() {
    return value ? 1231 : 1237;
}

Чому він використовує 1231 та 1237? Чому б не щось інше?


1
Ці два числа є досить великими простими числами. Будь ласка, прочитайте статтю на Хеш-таблиці у Вікіпедії для отримання додаткової інформації
Борис Павлович

Відповіді:


140

1231 і 1237 - це лише два (досить великі) довільні прості числа . Будь-які інші два великі прості числа були б чудовими.

Чому праймес?
Припустимо, на секунду, що ми вибрали складені числа (non-primes), скажімо, 1000 та 2000. Під час вставлення булей у хеш-таблицю, true та false переходитимуть у 1000 % Nвідповідність відра 2000 % N(де Nкількість відра).

Тепер зауважте це

  • 1000 % 8 таке ж відро, що і 2000 % 8
  • 1000 % 10 таке ж відро, що і 2000 % 10
  • 1000 % 20 таке ж відро, що і 2000 % 20
  • ….

Іншими словами, це призведе до багатьох зіткнень .

Це тому, що факторизація 1000 (2 3 , 5 3 ) та факторизація 2000 (2 4 , 5 3 ) мають стільки загальних факторів. Таким чином, вибираються прості числа, оскільки вони навряд чи матимуть загальні коефіцієнти з розміром відра.

Чому великі прайми. Чи не зробили б це 2 та 3?
При обчисленні хеш-кодів для складених об'єктів звичайно додавати хеш-коди для компонентів. Якщо в хеш-наборі з великою кількістю відер використовуються занадто малі значення, існує ризик закінчитись нерівномірним розподілом об'єктів.

Чи мають значення зіткнення? Булеві все одно мають два різні значення?
Карти можуть містити булеві символи разом з іншими об’єктами. Крім того, як вказував Drunix, загальним способом створення хеш-функцій складених об'єктів є повторне використання хеш-кодних реалізацій підкомпонентів, і в цьому випадку добре повернути великі праймери.

Пов’язані запитання:


1
Я вважаю, що вони досить великі. Щоб отримати gcd більше 1, вам знадобиться принаймні 2*1231 = 2462відра. Чи зіткнення є проблемою в такій ситуації?
aioobe

2
Цікаво, що вони насправді не "досить великі", враховуючи те, що може вписатися в інт. Я припускаю, що вони достатньо великі, щоб добре працювати з JDK Hashtable, але все ще досить малі, щоб мінімізувати витрати на розрахунок.
Тіло

2
Так, мене теж вразило, що вони не такі великі. Але чи вірите ви, що більша вартість з більшими грунтами?
aioobe

3
@Thilo вам потрібно кратно один тисячу двісті тридцять одна * 1237 = 1,522,747 відра , перш ніж вони конфліктують, то є багато досить великий
тріскачка урод

2
Я б сказав, що приведення до зіткнень із кількістю ковшів насправді не є проблемою з булевими, але більше загальною побудовою того, як ми отримуємо хед-код складеного об'єкта, а саме шляхом множення хеш-кодів компонентів на деякі константи та додавання їх.
Друнікс

2

Крім усього сказаного вище, це також може бути невелике пасхальне яйце від розробників:

вірно: 1231 => 1 + 2 + 3 + 1 = 7

7 - це щасливе число в європейських традиціях;

false: 1237 => 1 + 2 + 3 + 7 = 13

13 (він же Диявол десяток) - нещасливе число.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.