Рубрики
Без рубрики

Сортировка хэш-карты в Java

Узнайте, как сортировать записи HashMap по их ключу или значению

Автор оригинала: baeldung.

1. введение

В этом кратком руководстве мы узнаем, как сортировать HashMap в Java .

Более конкретно, мы рассмотрим сортировку записей HashMap по их ключу или значению с помощью:

  • Древовидная карта
  • ArrayList и Collections.sort()
  • Набор деревьев
  • Использование Stream API , и, наконец,,
  • Использование библиотеки Guava

2. Использование древовидной карты

Как мы знаем, ключи в TreeMap сортируются в их естественном порядке . Это хорошее решение, когда мы хотим отсортировать пары ключ-значение по их ключу. Таким образом, идея состоит в том, чтобы поместить все данные из нашей HashMap в TreeMap .

Для начала давайте определим HashMap и инициализируем его некоторыми данными:

Map map = new HashMap<>();

Employee employee1 = new Employee(1L, "Mher");
map.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map.put(employee4.getName(), employee4);

Для класса Employee обратите внимание, что мы реализовали Comparable :

public class Employee implements Comparable {

    private Long id;
    private String name;

    // constructor, getters, setters

    // override equals and hashCode
    @Override
    public int compareTo(Employee employee) {
        return (int)(this.id - employee.getId());
    }
}

Затем мы сохраняем записи в TreeMap с помощью его конструктора:

TreeMap sorted = new TreeMap<>(map);

Или метод putAll для копирования данных:

TreeMap sorted = new TreeMap<>();
sorted.putAll(map);

И это все! Чтобы убедиться, что наши записи на карте отсортированы по ключу, давайте распечатаем их:

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

Как мы видим, ключи отсортированы в естественном порядке.

3. Использование ArrayList

Конечно, мы можем отсортировать записи карты с помощью ArrayList . Ключевое отличие от предыдущего метода заключается в том, что мы не поддерживаем интерфейс Map здесь .

3.1. Сортировка по ключу

Давайте загрузим набор ключей в ArrayList :

List employeeByKey = new ArrayList<>(map.keySet());
Collections.sort(employeeByKey);

И выход есть:

[Annie, George, John, Mher]

3.2. Сортировка по значению

Теперь, что если мы хотим отсортировать наши значения карты по полю id объекта Employee ? Для этого мы также можем использовать ArrayList .

Во – первых, давайте скопируем значения в список:

List employeeById = new ArrayList<>(map.values());

И после этого мы его сортируем:

Collections.sort(employeeById);

Помните, что это работает, потому что Employee реализует Comparable interface . В противном случае нам нужно было бы определить ручной компаратор для нашего вызова Collections.сортировка .

Чтобы проверить результаты, мы печатаем employee By Id :

[Employee{id=1, name='Mher'}, 
Employee{id=2, name='George'}, 
Employee{id=8, name='John'}, 
Employee{id=22, name='Annie'}]

Как мы видим, объекты сортируются по их полю id .

4. Использование набора деревьев

В случае, если мы не хотим принимать повторяющиеся значения в нашей отсортированной коллекции, есть хорошее решение с TreeSet.

Во-первых, давайте добавим несколько дубликатов записей к нашей первоначальной карте:

Employee employee5 = new Employee(1L, "Mher");
map.put(employee5.getName(), employee5);
Employee employee6 = new Employee(22L, "Annie");
map.put(employee6.getName(), employee6);

4.1. Сортировка по ключу

Сортировка карты по ключевым элементам:

SortedSet keySet = new TreeSet<>(map.keySet());

Давайте напечатаем набор ключей и посмотрим на результат:

[Annie, George, John, Mher]

Теперь у нас есть ключи карты, отсортированные без дубликатов.

4.2. Сортировка по значению

Аналогично, для значений карты код преобразования выглядит следующим образом:

SortedSet values = new TreeSet<>(map.values());

И вот результаты:

[Employee{id=1, name='Mher'}, 
Employee{id=2, name='George'}, 
Employee{id=8, name='John'}, 
Employee{id=22, name='Annie'}]

Как мы видим, в выходных данных нет дубликатов. Это работает с пользовательскими объектами, когда мы переопределяем equals и hashCode.

5. Использование Лямбд и потоков

Начиная с Java 8, мы можем использовать Stream API и лямбда-выражения для сортировки карты . Все, что нам нужно, – это вызвать метод sorted по конвейеру stream карты.

5.1. Сортировка по ключу

Для сортировки по ключу мы используем компаратор comparingByKey comparator:

map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByKey())
  .forEach(System.out::println);

Итоговый для каждого этапа выводит результаты:

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

По умолчанию используется режим сортировки по возрастанию.

5.2. Сортировка по значению

Конечно, мы также можем сортировать объекты по Employee :

map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .forEach(System.out::println);

Как мы видим, приведенный выше код выводит карту, отсортированную по полям id объектов Employee :

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}

Кроме того, мы можем собрать результаты в новую карту:

Map result = map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .collect(Collectors.toMap(
    Map.Entry::getKey, 
    Map.Entry::getValue, 
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

Обратите внимание, что мы собрали наши результаты в LinkedHashMap . По умолчанию Collectors.toMap возвращает новую хэш-карту, но, как мы знаем, HashMap не гарантирует итерацию | order , while LinkedHashMap делает.

6. Использование Гуавы

Наконец, библиотека, которая позволяет нам сортировать HashMap , – это Guava. Прежде чем мы начнем, будет полезно проверить ваши записи о картах в Гуаве .

Во-первых, давайте объявим Ordering , поскольку мы хотим отсортировать нашу карту по полю Employee’s /Id :

Ordering naturalOrdering = Ordering.natural()
  .onResultOf(Functions.forMap(map, null));

Теперь все, что нам нужно, это использовать ImmutableSortedMap для иллюстрации результатов:

ImmutableSortedMap.copyOf(map, naturalOrdering);

И еще раз, выход-это карта, упорядоченная по полю id :

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}

7. Резюме

В этой статье мы рассмотрели несколько способов сортировки HashMap по ключу или по значению.

И мы внимательно рассмотрели, как мы можем это сделать, когда атрибут является пользовательским классом, реализуя Comparable .

Наконец, как всегда, код, используемый во время обсуждения, можно найти на GitHub .