Как вычисляется hashcode java
Hashcode в Java вычисляется с помощью метода hashCode() .
Он возвращает целочисленное значение, используемое для идентификации объекта. Для вычисления Java использует алгоритм хеширования, который преобразует данные объекта в целочисленное значение. Реализация алгоритма зависит от JVM.
public class App public static void main(String[] args) Object myObject = new Object(); System.out.println(myObject.hashCode()); // => 1995265320 String myStr = "Hello"; System.out.println(myStr.hashCode()); // => 69609650 Integer myInt = 5; System.out.println(myInt.hashCode()); // => 5 > >
Мы можем переопределить метод hashСode() для своих объектов. При этом необходимо учитывать следующее :
1) Согласно контракту методы hashCode() и equals() переопределяются одновременно.
2) Правила переопределения :
- вызов метода hashCode() один и более раз над одним и тем же объектом должен возвращать одно и то же хэш-значение, при условии что поля объекта, участвующие в вычислении значения, не изменялись.
- вызов метода hashCode() над двумя объектами должен всегда возвращать одно и то же число, если эти объекты равны (вызов метода equals() для этих объектов возвращает true).
- вызов метода hashCode() над двумя неравными между собой объектами должен возвращать разные хэш-значения. Хотя это требование и не является обязательным, следует учитывать, что его выполнение положительно повлияет на производительность работы хэш-таблиц.
3) Кроме того хороший хэшкод должен
- быстро вычисляться
- равномерно распределять значения для объектов класса
После переопределения первоначальный (идентификационный) хеш доступен через метод System.identityHashCode() .
15.12. Java – Метод hashCode()
Метод hashCode() – возвращает хэш-код для данной строки. Как вычисляется хэш-код для объекта String:
s[0]*31^(n-1) + s[1]*31^(n-2) + . + s[n-1]
Использование целочисленной арифметики, где s[i] – i-ый символ строки, n – длина строки, и ^ указывает на возведение в степень. (Хэш-значение пустой строки равно нулю).
Синтаксис
Синтаксис этого метода:
public int hashCode()
Параметры
Подробная информация о параметрах:
- Это метод по умолчанию, и он не будет принимать никаких параметров.
Возвращаемое значение
- В Java hashCode() возвращает значение хэш-кода для данного объекта.
Пример
import java.io.*; public class Test < public static void main(String args[])< String Str = new String("Добро пожаловать на ProgLang.su"); System.out.println("Хэш-код для Str: " + Str.hashCode()); >>
Получим следующий результат:
Хэш-код для Str: -773903428
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Хэш-код объекта, hashCode
В классе Object, который является родительским классом для объектов java, определен метод hashCode(), позволяющий получить уникальный целый номер для данного объекта. Когда объект сохраняют в коллекции типа HashSet, то данный номер позволяет быстро определить его местонахождение в коллекции и извлечь. Функция hashCode() объекта Object возвращает целое число int, размер которого равен 4-м байтам и значение которого располагается в диапазоне от -2 147 483 648 до 2 147 483 647.
Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.
public class HashCodeTest < public static void main(String[] args) < int hCode = (new Object()).hashCode(); System.out.println("hashCode = " + hCode); >>
Значение hashCode программы можно увидеть в консоли.
hashCode = 954599881
По умолчанию, функция hashCode() для объекта возвращает номер ячейки памяти, где объект сохраняется. Поэтому, если изменение в код приложения не вносятся, то функция должна выдавать одно и то же значение. При незначительном изменении кода значение hashCode также изменится.
Функция сравнения объектов equals()
В родительском классе Object наряду с функцией hashCode() имеется еще и логическая функция equals(Object)/ Функция equals(Object) используется для проверки равенства двух объектов. Реализация данной функции по умолчанию просто проверяет по ссылкам два объекта на предмет их эквивалентности.
Рассмотрим пример сравнения двух однотипных объектов Test следующего вида :
class Test < int f1 = -1; int f2 = -1; public Test (final int f1, final int f2) < this.f1 = f1; this.f2 = f2; >public int getF1() < return this.f1; >public int getF2() < return this.f2; >>
Создадим 2 объекта типа Test с одинаковыми значениями и сравним объекты с использованием функции equals().
public class EqualsExample < public static void main(String[] args) < Test obj1 = new Test(11, 12); Test obj2 = new Test(11, 12); System.out.println("Объекты :\n\tobj1 = " + obj1 + "\n\tobj2 = " + obj2); System.out.println("hashCode объектов :" + "\n\tobj1.hashCode = " + obj1.hashCode() + "\n\tobj2.hashCode = " + obj2.hashCode()); System.out.println("Сравнение объектов :" + "\n\tobj1.equals(obj2) = " + obj1.equals(obj2)); >>
Результат выполнения программы будет выведен в консоль :
Объекты : obj1 = example.Test@780324ff obj2 = example.Test@16721ee7 hashCode объектов : obj1.hashCode = 2013471999 obj2.hashCode = 376577767 Сравнение объектов : obj1.equals(obj2) = false
Не трудно было догадаться, что результат сравнения двух объектов вернет «false». На самом деле, это не совсем верно, поскольку объекты идентичны и в real time application метод должен вернуть true. Чтобы достигнуть этого корректного поведения, необходимо переопределить метод equals() объекта Test.
@Override public boolean equals(Object obj)
Вот теперь функция сравнения equals() возвращает значение «true». Достаточно ли этого? Попробуем добавить объекты в коллекцию HashSet и посмотрим, сколько объектов будет в коллекции? Для этого в в метод main примера EqualsExample добавим следующие строки :
Set objects = new HashSet(); objects.add(obj1); objects.add(obj2); System.out.println("Коллекция :\n\t" + objects);
Однако в коллекции у нас два объекта.
Коллекция : [example.Test@780324ff, example.Test@16721ee7]
Поскольку Set содержит только уникальные объекты, то внутри HashSet должен быть только один экземпляр. Чтобы этого достичь, объекты должны возвращать одинаковый hashCode. То есть нам необходимо переопределить также функцию hashCode() вместе с equals().
@Override public int hashCode()
Вот теперь все будет корректно выполняться — для двух объектов с одинаковыми параметрами функция equals() вернет значение «true», и в коллекцию попадет только один объект. В консоль будет выведен следующий текст работы программы :
Объекты : obj1 = example.Test@696 obj2 = example.Test@696 hashCode объектов : obj1.hashCode = 1686 obj2.hashCode = 1686 Сравнение объектов : obj1.equals(obj2) = true Коллекция : [example.Test@696]
Таким образом, переопределяя методы hashCode() и equals() мы можем корректно управлять нашими объектами, не допуская их дублирования.
Использование библиотеки commons-lang.jar для переопределения hashCode() и equals()
Процесс формирования методов hashCode() и equals() в IDE Eclipse автоматизирован. Для создания данных методов необходимо правой клавишей мыши вызвать контекстное меню класса (кликнуть на классе) и выбрать пункт меню Source (Class >> Source), в результате которого будет открыто следующее окно со списком меню для класса.
Выбираем пункт меню «Generate hachCode() and equals()» и в класс будут добавлены соответствующие методы.
@Override public int hashCode() < final int prime = 31; int result = 1; result = prime * result + f1; result = prime * result + f2; return result; >@Override public boolean equals(Object obj)
Библиотека Apache Commons включает два вспомогательных класса HashCodeBuilder и EqualsBuilder для вызова методов hashCode() и equals(). Чтобы включить их в класс необходимо внести следующие изменения.
import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; . @Override public int hashCode() < final int prime = 31; return new HashCodeBuilder(getF1()%2 == 0 ? getF1() + 1 : getF1(), prime).toHashCode(); >@Override public boolean equals(Object obj)
Примечание : желательно в методах hashCode() и equals() не использовать ссылки на поля, заменяйте их геттерами. Это связано с тем, что в некоторых технологиях java поля загружаются при помощи отложенной загрузки (lazy load) и не доступны, пока не вызваны их геттеры.
Скачать пример
Исходный код рассмотренного примера в виде проекта Eclipse можно скачать здесь (263 Kб).
Как работает метод hashCode () Java?
Java.lang.Object имеет методы, называемые hasCode(), и эти методы играют значительную роль в приложении реального времени. Объект hashCode() Object фактически является нативным методом, и реализация на самом деле не в чистой Java. Если посмотреть на источник Object Class, вы можете увидеть следующий код для hashCode.
public native int hashCode();
Это указывает на то, что hashCode — это собственная реализация, которая в определенной степени обеспечивает адрес памяти. Однако можно переопределить метод hashCode в вашем классе реализации. Родные методы являются либо внутренними, либо написанными за пределами Java в «родном» коде, то есть конкретным для данного компьютера.
Java не создает значимого хэш-кода для вас, это ваша работа как разработчик для создания полезного хэш-кода. Однако Object генерирует HashCode на основе адреса памяти экземпляра объекта. Большинство классов (особенно Collection API) должны реализовывать собственный HashCode (а по контракту — собственный метод equals). Значение, возвращаемое hashCode(), никоим образом не гарантируется как адрес памяти объекта. Согласно Java API, вычисление hashcode основано на 32-битном внутреннем адресе JVM (Java Virtual Machine) объекта. Верно, что объект перемещается во время выполнения. Но hashcode не меняется.
Пример
Student student1 = new Student(); person1.setName("John"); Student student2 = new Student(); person2.setName("Doe"); Student student3 = student2;
В приведенном выше случае student1.hashCode не будет равен student2.hashCode, потому что адреса памяти этих двух объектов не совпадают. Но student2.hashCode будет равен student3, потому что они указывают на один и тот же объект. Поэтому, если вам нужно использовать метод hashCode для ваших объектов, вы должны реализовать его самостоятельно.
Метод HashCode и Equals в Java
В Java каждый объект имеет доступ к методу equals(), поскольку он наследуется от класса Object. Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат. Вы должны переопределить hashCode() в каждом классе, который переопределяет equals(). Подробнее о . Метод HashCode и Equals
