Глубокое понимание разницы между HashMap и TreeMap
Введение
HashMap и TreeMap — два очень часто используемых класса в семействе Map.В чем разница между этими двумя классами в использовании и в природе? В этой статье мы проведем углубленное обсуждение этих двух аспектов, надеясь раскрыть их суть.
Существенная разница между HashMap и TreeMap
Сначала посмотрите на определение HashMap:
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
Посмотрите на определение TreeMap:
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
Из определения класса и HashMap, и TreeMap наследуют от AbstractMap, разница в том, что HashMap реализует интерфейс Map, а TreeMap реализует интерфейс NavigableMap. NavigableMap — разновидность SortedMap, реализующая сортировку ключей в Map.
Итак, первое различие между ними проявляется: TreeMap отсортирован, а HashMap — нет.
Давайте посмотрим на разницу между конструкторами HashMap и TreeMap.
public HashMap(int initialCapacity, float loadFactor)
В дополнение к конструктору без аргументов по умолчанию, HashMap также может принимать два параметра initialCapacity и loadFactor.
Базовая структура HashMap представляет собой массив узлов:
transient Node<K,V>[] table
initialCapacity — начальная емкость таблицы. Если вы не передаете initialCapacity, HashMap предоставляет значение по умолчанию:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
Когда в HashMap хранится слишком много данных, массив таблицы будет заполнен, и в это время требуется расширение, расширение HashMap осуществляется кратно 2. И loadFactor указывает, когда требуется операция расширения. Значение loadFactor по умолчанию равно 0,75.
static final float DEFAULT_LOAD_FACTOR = 0.75f;
Давайте рассмотрим еще несколько интересных переменных:
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
static final int MIN_TREEIFY_CAPACITY = 64;
Какие три переменные выше? До Java 8 метод разрешения конфликтов хэш-кода для HashMap был в форме связанного списка.Для повышения эффективности Java 8 преобразовала его в TreeNode. Когда будет отправлено это преобразование?
Это время зависит от двух переменных TREEIFY_THRESHOLD и UNTREEIFY_THRESHOLD.
Некоторые учащиеся могут найти, почему TREEIFY_THRESHOLD BRIDER 2? На самом деле я не знаю этой проблемы, но когда вы видите исходный код, используйте Untreeify_threshold, это = Treeify_threshold - 1, так что эти две переменные по сути одинаковы .
MIN_TREEIFY_CAPACITY указывает, что TREENODE разрешено, когда Таблица преобразует наименьшую емкость Treenode, разрешается преобразовывать только Capacity> = min_treeify_capacity.
Разница между TreeMap и HashMap заключается в том, что нижний слой TreeMap — это Entry:
private transient Entry<K,V> root
Его реализация — красно-черное дерево, удобное для обхода и поиска.
Конструктор TreeMap может передавать Comparator для реализации пользовательского метода сравнения.
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
Если пользовательский метод сравнения не указан, используется естественный порядок ключей.
Сортировать разницу
После того, как мы поговорили о природе двух сортировок, давайте рассмотрим пример и посмотрим на разницу между двумя сортировками:
@Test
public void withOrder(){
Map<String, String> books = new HashMap<>();
books.put("bob", "books");
books.put("c", "concurrent");
books.put("a", "a lock");
log.info("{}",books);
}
@Test
public void withOrder(){
Map<String, String> books = new TreeMap<>();
books.put("bob", "books");
books.put("c", "concurrent");
books.put("a", "a lock");
log.info("{}",books);
}
Для одного и того же кода, один использует HashMap, а другой использует TreeMap, мы обнаружим, что выходные результаты TreeMap отсортированы, а выходные результаты HashMap неопределенны.
Разница между нулевыми значениями
HashMap может допускать один нулевой ключ и несколько нулевых значений. В то время как TreeMap не разрешает нулевые ключи, но может разрешать несколько нулевых значений.
@Test
public void withNull() {
Map<String, String> hashmap = new HashMap<>();
hashmap.put(null, null);
log.info("{}",hashmap);
}
@Test
public void withNull() {
Map<String, String> hashmap = new TreeMap<>();
hashmap.put(null, null);
log.info("{}",hashmap);
}
HashMap сообщит: NullPointerException.
Разница в производительности
Нижним слоем HashMap является Array, поэтому HashMap будет очень быстро добавлять, искать, удалять и использовать другие методы. Нижний слой TreeMap представляет собой древовидную структуру, поэтому скорость будет ниже.
Кроме того, поскольку HashMap необходимо сохранить массив, это приведет к пустой трате места, в то время как TreeMap сохраняет только те узлы, которые необходимо сохранить, поэтому занимаемое пространство относительно невелико.
Если в HashMap есть конфликт хэшей, эффективность будет хуже, но после того, как Java 8 выполнит преобразование TreeNode, эффективность значительно повысится.
TreeMap будет переупорядочиваться при добавлении и удалении узлов, что повлияет на производительность.
точки соприкосновения
Ни один из них не допускает дублирования ключей, и ни один из них не является потокобезопасным.
Примеры этой статьиGitHub.com/Dadean2009/приходите…
Добро пожаловать, обратите внимание на мой публичный номер: вас ждут самые интересные вещи о программе! Для получения дополнительной информации, пожалуйста, посетитеwww.flydean.com