Как сгенерировать 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.

Напишите первое сообщение!

Вы должны войти под своим аккаунтом чтобы оставлять комментарии