Набор в Java - это набор, который не содержит дублирующих элементов или, если быть точным, пара элементов, которая не содержит e1.equals (E2). NULL разрешено в сете. Набор не может гарантировать порядок элементов в наборе.
При добавлении элемента для установки, если указанный элемент не существует, добавление успешно. То есть, если элемент E1 не существует в наборе (e == null? E1 == null: e.queals (e1)), то E1 может быть добавлен в набор.
Вот набор Hashset класса реализации в качестве примера, и кратко вводите принцип комплекта, чтобы не повторять реализацию:
пакет com.darren.test.overide; public Class CustomString {private String value; public customString () {this ("");} public CustomString (строка value) {this.value = value;}} Пакет com.darren.test.overide; import java.util.hashset; import java.util.set; public Class hashsettest {public static void main (string [] args) {string a = new String ("a"); строка b = новая строка ("a"); customString c = new CustomString ("b"); CustomString ("b"); System.out.println ("a.equals (b) ==" + a.equals (b)); system.out.println ("c.equals (d) ==" + c.equals (d)); set <object> set = new Hashset <object> (); set.add (a); set.add (b); set.add (c); set.add (d); system.out.println ("set.size () ==" + set.size ()); for (объект объекта: set) {system.out.println (object);}}}}}}}}}};Результаты работы следующие:
A.Equals (b) == true c.equals (d) == false set.size () == 3 com.darren.test.overide.customstring@2c39d2 a com.darren.test.overide.customstring@5795ce
Может быть, вы видели ключ, это верно, это метод равных. По -прежнему неуместно сказать это, но, если быть точным, это должны быть методы равных и хэшкодов. Почему ты это говоришь? Давайте изменим класс CustomString и протестируем его:
пакет com.darren.test.overide; public Class CustomString {private String value; public customString () {this ("");} public customString (строка) {this.value = value;}@переопределить публичный логический obj; return customstring.value.equals (value);} else {return false;}}}Результаты теста:
A.Equals (b) == true c.equals (d) == true set.size () == 3 com.darren.test.overide.customstring@12504e0 a com.darren.test.overide.customstring@1630eb6
Возвратное значение равных на это время верно, но размер набора все еще 3.
Давайте продолжим меняться
пакет com.darren.test.overide; public class CustomString {private String value; public customString () {this ("");} public CustomString (строка value) {this.value = value;}@переопределить public int hashcode () {// return super.hashcode (); возврат 1;}}Посмотрите на результаты еще раз:
A.Equals (b) == true c.equals (d) == false set.size () == 3 com.darren.test.overide.customstring@1 com.darren.test.overide.customstring@1 A
Только переписать метод хэшкода, а не переписать метод, либо
Наконец, изменить это
пакет com.darren.test.overide; public Class CustomString {private String value; public customString () {this ("");} public customString (строка) {this.value = value;}@переопределить публичный логический obj; return CustomString.value.equals (value);} else {return false;}}@переопределить public int hashcode () {// return super.hashcode (); возврат 1;}}Окончательные результаты:
A.Equals (b) == true c.equals (d) == true set.size () == 2 com.darren.test.overide.customstring@1 a
Хорошо, доказано, что вам нужно переписать метод Equals и метод хэшкода и увидеть принцип:
Конвенция о хэшкоде в java.lnag.object:
1. Во время выполнения приложения, если информация, используемая для сравнения метода Equals объекта, не изменяется, метод HashCode вызывается несколько раз на объекте, и он должен последовательно возвращать одно и то же целое число.
2. Если два объекта равны в соответствии с методом Equals (ObjectO), вызов метода HashCode любого из двух объектов должен получить одно и то же целое число.
3. Если два объекта не равны в соответствии с методом Equals (ObjectO), то используется метод хэшкода любого из двух объектов, и не требуются различные целочисленные результаты. Но если это может быть другим, это может улучшить производительность хэш -таблицы.
В Hashset основные операции реализуются с помощью уровня HashMap, потому что уровень хэшсет использует HashMap для хранения данных. При добавлении элемента в хэшсет сначала вычислите значение хешкода элемента, а затем используйте этот (хэшкод элемента)% (размер коллекции HashMap) + 1 для расчета места хранения этого элемента. Если эта позиция пуста, добавьте элемент; Если он не пуст, используйте метод Equals, чтобы сравнить, равны ли элементы, а если равны, не добавляйте его, в противном случае найдите пустое пространство, чтобы добавить его.
Ниже приводится часть исходного кода хэшса:
Package java.util; Hashset public Class <e> расширяет AbstractSet <e> Реализации SET <e>, Clonable, Java.io.serializable {Static Final Long SerialVersionUid = -50247444067133321676L; // Основной слой использует HASHMAP для спасения всех элементов в сайте. Частный переходной хэшмап <e, Object> Map; // Определить объект виртуального объекта как значение HashMap и определить этот объект как статический финал. Приватный статический конечный объект Present = new Object ();/*** Конструкторы без параметра по умолчанию конструирует пустой хэшсет. * * Фактически, базовый слой будет инициализировать пустой хэшмап и использовать начальную емкость по умолчанию 16 и коэффициент загрузки 0,75. */public hashset () {map = new hashmap <e, object> ();}/*** Создайте новый набор, содержащий элементы в указанной коллекции. * * Фактический базовый слой использует коэффициент загрузки по умолчанию 0,75 и достаточно, чтобы сдержать начальную емкость всех элементов в указанной * сборе для создания хэшмапа. * @param c Элементы в нем будут храниться в коллекции в этом наборе. */public hashset (collection <extends e> c) {map = new hashmap <e, object> (math.max ((int) (c.size ()/. 75f) + 1, 16)); addall (c);}/*** Создание пустого хэшса с указанной начальной способностью и нагрузкой. * * Фактический базовый слой конструирует пустой хэшмап с соответствующими параметрами. * @param initialCapacity Начальная емкость. * @param коэффициент загрузки нагрузки. */public hashset (int initialCapacity, float loadFactor) {map = new HashMap <E, Object> (initialCapacity, LoadFactor);}/*** Создание пустого хэшса с указанной начальной каплей. * * Фактически, базовый слой конструирует пустой хэшмап с соответствующими параметрами и коэффициентом нагрузки нагрузки 0,75. * @param initialCapacity Начальная емкость. */public hashset (int initialCapacity) {map = new Hashmap <e, Object> (initialCapacity);}/*** Создание новой пустой хэш -коллекции ссылки с указанной начальной капочностью и нагрузкой. * Этот конструктор является разрешением на доступ к пакетам и не подвергается воздействию общественности. На самом деле это просто поддержка LinkedHashset. * * Фактически, базовый уровень будет построить пустой экземпляр LinkedHashmap с указанными параметрами для его реализации. * @param initialCapacity Начальная емкость. * @param коэффициент загрузки нагрузки. * @param Dummy Tag. */Hashset (int initycapacity, float loadfactor, boolean dummy) {map = new LinkedHashmap <e, Object> (initialCapacity, loadfactor);}/*** Возвращает итератор, который итерации в этом наборе. Порядок возвращаемых элементов не является конкретным. * * Основной слой фактически называет клавиш базового HashMap, чтобы вернуть все ключи. * Можно увидеть элементы в хешсете, но хранятся на ключе базового HashMap, и значение идентифицируется статическим объектом конечного объекта. * @return итератор, который итерация над элементами в этом наборе. */@Переопределить публичный итератор <e> iterator () {return map.keyset (). Iterator ();}/*** Возвращает количество элементов в этом наборе (емкость набора). * * Основной слой фактически вызывает метод HashMap Size (), чтобы вернуть количество записи, и получает количество элементов в наборе. * @return Количество элементов в этом наборе (емкость набора). */@Переопределить public int size () {return map.size ();}/*** return true, если этот набор не содержит никаких элементов. * * Основной слой фактически вызывает isempty () Hashmap, чтобы определить, пустого ли хэшсет. * @return return true, если этот набор не содержит никаких элементов. */@Переопределить публичный логический isempty () {return map.isempty ();}/*** return true, если этот набор содержит указанный элемент. * Более конкретно, true возвращается тогда и только тогда, когда этот набор содержит E -элемент, который удовлетворяет (O == NULL? E == NULL: O.Equals (e)) *. * * Содержимое основного фактического вызова HashMap определяет, содержит ли он указанный ключ. * @param o Существование элемента в этом наборе было проверено. * @return return true, если этот набор содержит указанный элемент. */@Override public boolean содержит (Object o) {return map.containskey (o);}/*** Если указанный элемент не включен в этот набор, добавьте указанный элемент. * Более конкретно, если этот набор не содержит элемента E2, который удовлетворяет (e == null? E2 == null: e.equals (e2)) *, к этому набору добавляется указанный элемент e. * Если этот набор уже содержит элемент, вызов не изменяет набор и возвращает false. * * Основной слой фактически поместит элемент в качестве ключа в хэшмату. * Поскольку метод hashmap's put () добавляет пару клавишных значений, когда ключ в новой записи Hashmap * такой же, как и ключ исходной записи в коллекции (hashcode (), и он также возвращает истину через сравнение равных), * значение недавно добавленной записи будет перезаписать значение исходного записи, но ключ не изменит любого. * Поэтому, если существующий элемент добавляется в хэшсет, вновь добавленный элемент сбора не будет помещен в HashMap, и * исходный элемент не будет изменять ни одного, что удовлетворяет особенности не повторного коветации элементов в наборе. * @param E Элементы, которые будут добавлены в этот набор. * @return return true, если этот набор не содержит указанный элемент. */@Переопределить публичный логический add (e e) {return map.put (e, present) == null;}/*** Если указанный элемент существует в этом наборе, он будет удален. * Более конкретно, если этот набор содержит элемент E, который удовлетворяет (O == NULL? E == NULL: O.Equals (e)), * удалит его. Верните True, если этот набор уже содержит элемент (или: true, если этот набор изменяется из -за вызова). (Как только вызов возвращается, этот набор больше не содержит элемент). * * Основной слой фактически вызывает метод удаления хэшмапа, чтобы удалить указанную запись. * @param o объект, который необходимо удалить, если он существует в этом наборе. * @return return true Если установка содержит указанный элемент. */@Переопределить публичное логическое удаление (объект o) {return map.remove (o) == present;}/*** Удалить все элементы из этого набора. После возвращения этого вызова набор будет пустым. * * Основной слой фактически вызывает четкий метод хэшмапа, чтобы очистить все элементы во входе. */@Переопределить public void clear () {map.clear ();}}Суммировать
Вышеупомянутое содержимое этой статьи об анализе принципа удаления хэшса -репутационных значений. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!