Як згенерувати hashCode в Java

жовтня
04
2012
Мітки: hashcode java

Якщо в Java Ви використовуєте об'єкт власного класу в якості наповнювача для колекцій HashSet, HashMap, Hashtable або будь-яких інших колекцій, які зберігають об'єкти в групах, то Вам також необхідно перевизначити метод hashCode(). Це необхідно для правильної і більш ефективної роботи з колекціями. Також завжди необхідно перевизначати метод hashCode() якщо Ви перевизначили метод equals(). У цій статті буде розказано як це зробити.

Всі класи успадковують базову реалізацію hashCode() класу java.lang.Object, але краще перевизначати цей метод для більш ефективної обробки специфічних даних.

Метод hashCode() повертає значення int (4 байти), яке є числовим представленням об'єкта. Цей хеш-код використовується, наприклад, колекціями для більш ефективного зберігання даних і, відповідно, більш швидкого доступу до них.

Для одного і того ж об'єкта метод hashCode() повинен повертати одне і те ж значення протягом всього "життя" об'єкта.

Також при перевизначенні методу equals() необхідно пам'ятати, що для однакових об'єктів наступна умова має бути істинною:


object1.hashCode() == object2.hashCode()

При перевизначенні equals() завжди перевизначайте hashCode().

Зауважте також, що якщо в різних об'єктів однаковий хеш, то це може говорити про те, що обчислення хеш-коду не є ефективним. Але це не завжди істинне твердження. Наприклад, якщо у Вас декілька мільйонів або мільярдів різних примірників одного і того ж класу, то є висока ймовірність того, що з'явиться два об'єкти з однаковим хеш-кодом. У будь-якому випадку, різний хеш для різних об'єктів не є обов'язковою вимогою.

Дотримуйтесь наступних загальноприйнятих правил при перевизначенні методу hashCode():

Нижче представлений приклад застосування вищевказаних правил


public class TestClass {
    private boolean booleanValue = true;
    private char charValue = 'd';
    private String stringValue = "TestClass";
    private long longValue = 34829245849498300l;
    private float floatValue = 345832400.93f;
    private double doubleValue = 98584292348454.9834;
    private byte[] arrayValue = {1, 2, 3};

    @Override
    public int hashCode() {
        int result = 17;
        
        result = 37 * result + ( booleanValue ? 1 : 0 );
        result = 37 * result + (int) charValue;
        result = 37 * result + (stringValue == null ? 0 : stringValue.hashCode());
        result = 37 * result + (int)(longValue - (longValue >>> 32));
        result = 37 * result + Float.floatToIntBits(floatValue);
        long longBits = Double.doubleToLongBits(doubleValue);
        result = 37 * result + (int)(longBits - (longBits >>> 32));
        for( byte b : arrayValue )
            result = 37 * result + (int) b;
        
        return result;
    }
    
}

Якщо Ваша хеш-функція вимагає багато часу для обчислення хеш-коду, Ви можете зберігати його значення (отримане на етапі ініціалізації або при першому зверненні до об'єкта). Не забувайте при цьому, що при зміні даних об'єкту, необхідно перерахувати його хеш-код.

Якщо в класі відсутнє перевизначення методу toString(), то метод toString() поверне рядок виду ClassName@(результат виконання функції hashCode() в шістнадцятковому вигляді). Наприклад, MyClass@152b6651.

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі