Автор оригинала: David Landup.
В этом уроке мы рассмотрим как сортировать хэш-карту по ключу в Java .
Давайте продолжим и создадим простую Хэш-карту
:
MapunsortedMap = new HashMap(); unsortedMap.put("John", 21); unsortedMap.put("Maria", 34); unsortedMap.put("Mark", 31); unsortedMap.put("Sydney", 24); unsortedMap.entrySet().forEach(System.out::println);
У нас есть Строка
s в качестве ключей и Целое число
s в качестве значений. В большинстве случаев вы будете сталкиваться с Целым числом
s или Строкой
s в качестве ключей и пользовательскими объектами, Строкой
s или Целым числом
s в качестве значений. Мы хотим отсортировать эту Хэш-карту
на основе ключей String
.
HashMap
s не гарантирует сохранение порядка его элементов в любом случае. Порядок может меняться со временем, и наиболее определенно не будет напечатан обратно в порядке вставки:
John=21 Mark=31 Maria=34 Sydney=24
Если вы повторно запустите эту программу, она сохранит этот порядок, так как HashMap
упорядочивает свои элементы в ячейки на основе хэш-значения ключей. При печати значений из HashMap
его содержимое печатается последовательно , поэтому результаты останутся прежними, если мы повторно запустим программу несколько раз.
Сортировка хэш-карты по ключу с помощью карты деревьев
Карта дерева
расширяет интерфейс SortedMap
, в отличие от реализации HashMap
. Древовидная карта
s означает быть отсортированным аналогом, однако Древовидная карта
s только сортируется по ключам , учитывая компаратор.
Сортировка Строковых Ключей Лексикографически
Создать древовидную карту
с учетом Хэш-карты
так же просто , как предоставить вызову конструктора несортированную карту:
MapsortedMap = new TreeMap<>(unsortedMap); sortedMap.entrySet().forEach(System.out::println);
Выполнение этого кода приводит к:
John=21 Maria=34 Mark=31 Sydney=24
Поскольку мы не предоставили никакого компаратора, включается компаратор по умолчанию, используемый для строк. В частности, при сравнении строк метод compareTo()
сравнивает лексикографическое значение каждой строки и сортирует их в порядке возрастания.
Мы увидим имена , начинающиеся с A
, перед именами, начинающимися с B
и т. Д. Давайте добавим два новых имени и посмотрим, что произойдет:
unsortedMap.put("Adam", 35); unsortedMap.put("Aaron", 22); MapsortedMap = new TreeMap<>(unsortedMap); sortedMap.entrySet().forEach(System.out::println);
Это приводит к:
Aaron=22 Adam=35 John=21 Maria=34 Mark=31 Sydney=24
Сортировка ключей с помощью пользовательского компаратора
Действительно приятная особенность заключается в том, что мы можем предоставить новый компаратор()
для Карты деревьев
и указать в нем нашу собственную логику сравнения. Например, давайте посмотрим, как мы можем сортировать ключи строк по длине в хэш-карте
, используя длину
строк и пользовательский компаратор:
MapsortedMap = new TreeMap<>(new Comparator () { @Override public int compare(String o1, String o2) { int lengthDifference = o1.length() - o2.length(); if (lengthDifference != 0) return lengthDifference; return o1.compareTo(o2); } }); sortedMap.putAll(unsortedMap); sortedMap.entrySet().forEach(System.out::println);
Здесь мы построили древовидную карту
с помощью пользовательского Компаратора
и в переопределенном методе сравнения()
мы указали желаемую логику.
Поскольку у нас нет гарантии, что o1.length() - o2.length()
не будет 0, простое if-утверждение гарантирует, что мы сравним их лексикографически, если их длины одинаковы.
Затем, как только мы определили критерии сортировки для Карты деревьев
, мы использовали метод putAll()
для вставки всех элементов из Несортированной карты
в Отсортированную карту
.
Выполнение этого кода приводит к:
Adam=35 John=21 Mark=31 Aaron=22 Maria=34 Sydney=24
Карта теперь сортируется с помощью пользовательского Компаратора
, который в этом случае сравнивает длину
с Строк
ключей. Вы можете использовать любую логику здесь, чтобы удовлетворить ваши конкретные потребности.
Сортировка хэш-карты по ключу с помощью LinkedHashMap
LinkedHashMap
сохраняет порядок вставки. Он содержит двусвязный список всех записей, что позволяет вам очень естественно получать доступ к его элементам и перебирать их.
Итак, самый простой способ преобразовать несортированную Хэш-карту
в связанную хэш-карту
– это добавить элементы в том порядке, в котором мы хотели бы их видеть.
Сортировка Ключей хэш-карты Лексикографически
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
Теперь давайте продолжим и отсортируем несортированную карту
, создав новую Связанную карту
, которая будет содержать элементы в отсортированном порядке.
В классе Map.Entry
есть очень удобный метод , который вступает в игру здесь – comparingByKey ()
, который сравнивает ключи, если у них есть допустимые методы сравнения. Поскольку мы имеем дело с Строкой
s, это метод compareTo ()
, который еще раз отсортирует Строку
s лексикографически:
MapsortedMap = unsortedMap.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { throw new AssertionError(); }, LinkedHashMap::new )); sortedMap.entrySet().forEach(System.out::println);
То, что мы здесь сделали, – это потоковое | Несортированное изображение набор объектов
Map.Entry . Затем, используя метод
sorted () , мы предоставили удобный
Компаратор , созданный
comparingByKey () , который сравнивает данные объекты с их реализацией сравнения по умолчанию.
После сортировки мы собираем()
их, используя Collectors.toMap()
, в новую карту. Конечно, мы будем использовать те же ключи и значения из исходной карты, используя ссылки на методы Map.Entry::getKey
и Map.Entry::GetValue
.
Наконец, создается новый LinkedHashMap
, в который вставляются все эти элементы в отсортированном порядке.
Выполнение этого кода приводит к:
Aaron=22 Adam=35 John=21 Maria=34 Mark=31 Sydney=24
Сортировка ключей хэш-карты с помощью пользовательского компаратора
В качестве альтернативы вы можете использовать свой собственный Компаратор
вместо того, который был создан Map.Entry.comparingByKey()
. Это так же просто, как ввести Comparator.comparing()
и передать в него допустимое Лямбда-выражение :
MapsortedMap = unsortedMap.entrySet().stream() .sorted(Comparator.comparing(e -> e.getKey().length())) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { throw new AssertionError(); }, LinkedHashMap::new )); sortedMap.entrySet().forEach(System.out::println);
Здесь мы воссоздали наш пользовательский компаратор, который сортирует ключи по их значению из предыдущих разделов. Теперь ключи String
будут отсортированы по их длине, а не по их лексикографическому значению:
Adam=35 John=21 Mark=31 Aaron=22 Maria=34 Sydney=24
Конечно, вы можете легко переключиться с возрастающего порядка на убывающий, просто добавив -
перед e.getKey().length()
:
MapsortedMap = unsortedMap.entrySet().stream() .sorted(Comparator.comparing(e -> -e.getKey().length())) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { throw new AssertionError(); }, LinkedHashMap::new )); sortedMap.entrySet().forEach(System.out::println);
Это приводит к:
Sydney=24 Aaron=22 Maria=34 Adam=35 John=21 Mark=31
Кроме того, вы можете использовать другие компараторы, такие как Comparator.comparingInt()
если вы имеете дело с целочисленными значениями (мы здесь, однако, также работает общий компаратор), Comparator.comparingDouble()
или Comparator.comparingLong()
в соответствии с вашими потребностями.
Вывод
В этом уроке мы рассмотрели, как сортировать хэш-карту Java по ключу . Первоначально мы использовали древовидную карту
для сортировки и поддержания порядка отсортированных записей, как с использованием компаратора по умолчанию, так и пользовательского.
Затем у нас есть потоки Java 8 с классом LinkedHashMap
для достижения этой функциональности, как для стандартных, так и для пользовательских компараторов в порядке возрастания и убывания.