Сравнение нескольких способов оценить одни и те же элементы хэшмапа, хэшса, тройка и деревьев на Java
1.1 Hashmap
Давайте сначала взглянем на то, как элементы хранятся в HashMap. Каждый элемент, хранящийся на карте, представляет собой пару клавишных значений, такую как клавиш, и добавляется с помощью метода PUT. Кроме того, тот же ключ будет иметь только значение, связанное с ним на карте. Метод POT определяется на карте следующим образом.
V put (k ключ, v Значение);
Он используется для хранения пары клавиш, например, клавиш. Возвращаемое значение - это старое значение, хранящееся на карте с помощью ключа. Если его не существует ранее, он вернет нуль. Вот как реализован метод HOSHMAP.
public v put (k key, v value) {if (key == null) return putfornullkey (value); int hash = hash (ключ); int i = indexfor (hash, table.length); for (intry <k, v> e = table [i]; e! = null; e = e.next) {объект k; if (e.hash == hash && ((k = e.key) == key || key.equals (k))) {v oldvalue = e.value; e.value = значение; e.recordaccess (это); вернуть OldValue; }} modcount ++; AddEntry (хэш, ключ, значение, i); вернуть ноль; }Из вышесказанного мы видим, что при добавлении соответствующей комбинации клавиш значения, если соответствующий ключ уже существует, соответствующее значение будет изменено напрямую, а старое значение будет возвращено. Судя о том, существует ли ключ, сначала сравнивается хэшкод ключа, а затем хэшкод ключа сравнивается с равными или равными. Возможно, мы не сможем увидеть это здесь. Из приведенного выше кода мы сравниваем хэшкод Map.Entry и Hashcode Key. На самом деле, мы видим, что Hashcode Map.Entry на самом деле является хэшкодом своего ключа. Если соответствующий ключ не существует изначально, AddEntry будет вызвана, чтобы добавить соответствующее значение ключа к карте. Хэш параметров, переданный аддюшн, является хэшкодом, соответствующим ключу. Далее, давайте посмотрим на определение метода добавления.
void AddEntry (int hash, k -ключ, v Значение, int bucketIndex) {if ((size> = threshold) && (null! = table [bucketindex])) {resize (2 * table.length); хэш = (null! = ключ)? хэш (ключ): 0; bucketindex = indexfor (hash, table.length); } createEntry (хэш, ключ, значение, bucketIndex); } void createEntry (int hash, k key, v value, int bucketindex) {inpit <k, v> e = table [bucketindex]; Таблица [BucketIndex] = Новая запись <> (хэш, ключ, значение, E); размер ++; }Ядром добавления является вызов CreateEntry, чтобы создать объект Map.Entry, представляющий соответствующее значение ключа, и сохранить его. Очевидно, что приведенная выше таблица представляет собой массив Map.Entry. Map.Entry использует хэш свойств для сохранения хэшкода соответствующего ключа. Давайте посмотрим на конструктор Map.Entry, названное выше.
Inpit (int h, k k, v v, intry <k, v> n) {value = v; Next = N; Key = k; хэш = h; }Очевидно, это сохраняет хэшкод, соответствующий соответствующему клавишу, значению и клавишу.
После понимания того, как HashMap хранит элементы, легче понять, как хэшмап хранит элементы. В HashMap есть два основных метода, чтобы определить, являются ли элементы одинаковыми. Одним из них является определение того, является ли ключ такой же, а другой - определить, является ли значение одинаковым. Фактически, при представлении того, как хэшмап хранит элементы, мы представили, как HashMap определяет, такой же ключ элемента. То есть, прежде всего, хэшкод одинаков, а во -вторых, клавиши равны или равны. Определение того, является ли ключ одинаковым на карте, выполняется с помощью метода sontainskey (), и его реализация в Hashmap заключается в следующем.
public boolean содержит (объектно -ключ) {return getEntry (key)! = null; } окончательная запись <K, v> getEntry (object key) {int hash = (key == null)? 0: хэш (ключ); for (inpit <k, v> e = table [indexfor (hash, table.length)]; e! = null; e = e.next) {объект k; if (e.hash == hash && ((k = e.key) == key || (key! = null && key.equals (k))) return e; } return null; }Очевидно, что сначала определяет, является ли хэшкод ключа одинаковой, а затем определяет, является ли ключ равным или равным.
Значение, используемое в карте, оценивается методом SocidainsValue, и его реализация в HashMap заключается в следующем.
public boolean содержит Value (значение объекта) {if (value == null) return containsnullvalue (); Inpit [] tab = table; for (int i = 0; i <tab.length; i ++) для (запись e = tab [i]; e! = null; e = e.next) if (value.equals (e.value)) вернуть true; вернуть ложь; }Очевидно, что значение не нулевой формы оценивается по равным значению, а нулевая форма равна, если она равна, то есть значение в сохраненном элементе равна нуле.
1.2 Hashset
Узнав, как HashMap хранит элементы и определяет, являются ли элементы одинаковыми, легче увидеть, как хешет определяет, являются ли элементы одинаковыми.
Элементы в хешсете фактически сохраняются через HashMap. Каждый объект Hashset содержит ссылку на соответствующий объект HashMap. При добавлении и удалении элементов в хэшсет он выполняется через хэшмап, который он удерживает. При сохранении элемента он сохранит соответствующий элемент в качестве ключа удерживаемого хэшмапа. Соответствующее значение является постоянным объектом, поэтому при его сохранении он использует логику определения того, являются ли элементы одинаковыми. При определении того, включен ли элемент, он также вызывает содержимый метод хэшмапа, который проводится для вынесения суждений.
public boolean содержит (Object o) {returnmap.containskey (o); }Друзья, которые заинтересованы, могут проверить исходный код хэшса.
1.3 Тримп
Элементы, хранящиеся в TreeMap, заказаны и отсортируются в соответствии с ключом. У TreeMap есть два способа сортировки хранимых элементов. Один из них состоит в том, чтобы сортировать компаратор, который он удерживает, а другой - сортировать ключ, который реализует сопоставимый интерфейс. Первый метод предпочтительнее. Когда удерживаемый компаратор (по умолчанию null) является нулевым, используется второй метод. TreeMap имеет несколько конструкторов, через которые может быть инициализирован компаратор, который он удерживает. Давайте сначала посмотрим, как TreeMap сохраняет элементы. Метод POT реализуется следующим образом.
public v put (k key, v value) {inpit <k, v> t = root; if (t == null) {compare (key, key); // введите (и возможный null) проверьте root = новая запись <> (ключ, значение, null); размер = 1; modcount ++; вернуть ноль; } int cmp; Вход <K, V> родитель; // разделить компаратор и сопоставимые пути компаратор <? Super k> cpr = компаратор; if (cpr! = null) {do {parent = t; cmp = cpr.compare (key, t.key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; else return t.setValue (значение); } while (t! = null); } else {if (key == null) брошен NullPointerException (); Сопоставимо <? Super K> k = (сопоставимый <? Super K>) ключ; do {parent = t; cmp = k.compareto (t.key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; else return t.setValue (значение); } while (t! = null); } Inpit <K, v> e = новая запись <> (ключ, значение, родитель); if (cmp <0) parent.left = e; else parent.right = e; fixafterinsertion (e); размер ++; modcount ++; вернуть ноль; }Из приведенной выше реализации мы видим, что первый элемент будет храниться напрямую. Следующие элементы делятся на две ситуации, одна из них - тот случай, когда удерживающий компаратор не является пустым, а другой - тот случай, когда удерживаемый компаратор пуст. Когда компаратор не пуст, компаратор определит местоположение хранимого элемента. Одна важная вещь заключается в том, что когда результат сравнения ключа существующего элемента с ключом текущего хранимого элемента составляет 0, будет считаться, что ключ из хранимого в настоящее время элемента уже существует на исходной карте, а затем значение, соответствующее исходному ключу, изменяется на новое значение, а затем старое значение возвращается напрямую. Когда удерживаемый компаратор пуст, местоположение элемента будет определяться методом Compareto ключа, который реализует сопоставимый интерфейс. Одна вещь, похожая на использование компаратора, заключается в том, что когда оригинальный ключ сравнивается с недавно сохраненным ключом, составляет 0, будет считаться, что недавно сохраненный ключ уже существует на исходной карте, а значение соответствующего исходного ключа будет изменена напрямую, а пара клавиш больше не будет храниться. Фактически, основная логика реализации метода содержит, которая определяет, является ли элемент одинаковой, и конкретная реализация заключается в следующем.
public boolean содержит (объектно -ключ) {return getEntry (key)! = null; } Окончательная запись <K, v> getEntry (object key) {// Версия на основе сравнения на основе выгрузки для производительности if (Comparator! = null) return getEntryusingComparator (key); if (key == null) брошен NullPointerException (); Сопоставимо <? Super K> k = (сопоставимый <? Super K>) ключ; Запись <K, v> p = root; while (p! = null) {int cmp = k.compareto (p.key); if (cmp <0) p = p.left; elseif (cmp> 0) p = p.right; иначе вернуть P; } return null; }Поскольку логика TreeMap, чтобы определить, существует ли элемент, чтобы определить, является ли результат после сравнения компаратора или сопоставимого, 0, мы должны быть особенно осторожны при использовании TreeMap для реализации какой -то логики, аналогичной равным элементам.
Логика TreeMap содержит Value, чтобы определить, равно ли соответствующее значение? Похоже на HashMap. Заинтересованные друзья могут проверить исходный код TreeMap.
1.4 Treesset
Treesset также является реализацией набора. Хранящие элементы не повторяются и заказаны. По умолчанию хранимые элементы должны реализовать сопоставимый интерфейс, потому что по умолчанию элементы будут сравниваться как сопоставимые объекты. Treesset также можно использовать для сравнения элементов, хранящихся в нем через компаратор. Это может быть достигнуто путем прохождения в объекте компаратора или TreeMap, удерживающего объект компаратора при построении деревьев. Реализация Treesset аналогична реализации Hashset. Он также содержит ссылку на карту, но она относится не к Hashmap, а TreeeMap. Добавление и удаление элементов в деревьях все реализованы в TreeMap, который они держат. Следовательно, аналогично Hashset, способ определения того, соответствуют ли элементы в деревьях, соответствуют TREEMAP, а также определяются через компаратор или сопоставимый, а не традиционный метод Equals. Заинтересованные друзья могут проверить исходный код деревьев.
Спасибо за чтение, я надеюсь, что это поможет вам. Спасибо за поддержку этого сайта!