Статьи Утилиты Telegram YouTube Отзывы

SequencedMap

Видеогайд

8 ноября 2023

Тэги: Collections, Java, ООП.

Содержание

  1. Добавление первых и последних элементов
  2. Удаление первых и последних элементов
  3. Доступ к первому и последнему элементу
  4. Получение множеств ключей и значений
  5. Итоги

В статье SequencedCollection и SequencedSet в Java мы рассмотрели интерфейс SequencedCollection, который появился в Java 21. Также узнали про его более частный случай – интерфейс SequencedSet.

Теперь перейдём к интерфейсу SequencedMap, который обладает сходным функционалом, но не входит напрямую в иерархию SequencedCollection.

interface SequencedMap<K, V> extends Map<K, V> {
    SequencedMap<K, V> reversed();
    Map.Entry<K,V> firstEntry();
    Map.Entry<K,V> lastEntry();
    Map.Entry<K,V> pollFirstEntry();
    Map.Entry<K,V> pollLastEntry();
    V putFirst(K k, V v);
    V putLast(K k, V v);
    SequencedSet<K> sequencedKeySet();
    SequencedCollection<V> sequencedValues();
    SequencedSet<Map.Entry<K, V>> sequencedEntrySet();
}

Этот интерфейс расширяет стандартный Map, добавляя в него методы для доступа и манипулирования первым и последним элементами. В отличие от SequencedCollection, здесь мы манипулируем не отдельными значениями, а сразу парой «ключ-значение», представленной Map.Entry.

Помимо этого, мы можем отдельно получать множество упорядоченных ключей и упорядоченных значений. Ну и уже привычный нам метод reversed(), который позволяет обходить мапу в обратном порядке.

По аналогии с SequencedSet, интерфейс SequencedMap поддерживается классами LinkedHashMap и TreeMap. При этом HashMap не поддерживает интерфейс SequencedMap, потому что изначально не гарантирует порядок.

Упрощённая иерархия классов и интерфейсов, связанных с SequencedMap, представлена на этой схеме:

Иерархия классов и интерфейсов SequencedMap

Добавление первых и последних элементов

Если мы возьмём за основу LinkedHashMap, то метод putLast(), добавляющий элемент в конец мапы, будет действовать аналогично стандартному put(), т.к. данный вид мапы сохраняет порядок добавления. В начало мапы в любой момент можно добавить с помощью putFirst().

SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.putLast("bbb", 456); // аналог put()
map.putLast("ccc", 789);
map.putFirst("aaa", 123);
System.out.println(map); // {aaa=123, bbb=456, ccc=789}
System.out.println(map.reversed()); // {ccc=789, bbb=456, aaa=123}

Для вывода содержимого мапы в обратном порядке используем метод reversed().

Класс TreeMap хоть и поддерживает интерфейс SequencedMap, но не поддерживает методы добавления первого и последнего элемента, т.к. этот вид мапы всегда сортирует ключи в алфавитном порядке, а потому сам «знает», какой элемент должен быть «первым», а какой – «последним».

SequencedMap<String, Integer> map = new TreeMap<>();
//map.putLast("bbb", 456); // UnsupportedOperationException
map.put("ccc", 789);
map.put("aaa", 123);

При попытке вызвать метод putFirst() или putLast() мы получим UnsupportedOperationException. Поэтому в TreeMap добавление элементов делаем через старый добрый put().

Удаление первых и последних элементов

Удаление элементов мы делаем с помощью методов pollFirstEntry() и pollLastEntry(). Они удаляют элемент из мапы и возвращают его в качестве результата. Если мапа будет пустая, они не кидают ошибку и просто возвращают null.

И здесь особой разницы между LinkedHashMap и TreeMap нет, поскольку для TreeMap тоже всегда известен «первый» и «последний» элемент.

SequencedMap<String, Integer> map = new TreeMap<>();
map.put("bbb", 456);
map.put("ccc", 789);
map.put("aaa", 123);
System.out.println(map.pollFirstEntry()); // aaa=123
System.out.println(map.pollLastEntry()); // ccc=789
System.out.println(map); // {bbb=456}
map.clear();
System.out.println(map.pollLastEntry()); // null

Доступ к первому и последнему элементу

Для получения первого и последнего элементы мы используем методы getFirstEntry() и getLastEntry().

SequencedMap<String, Integer> map = new TreeMap<>();
map.put("bbb", 456);
map.put("ccc", 789);
map.put("aaa", 123);
System.out.println(map.firstEntry()); // aaa=123
System.out.println(map.lastEntry()); // ccc=789
map.clear();
System.out.println(map.lastEntry()); // null

Если мапа пустая, методы будут возвращает null так же, как и при удалении. Поэтому разницы между LinkedHashMap и TreeMap здесь нет.

Получение множеств ключей и значений

Как и в случае с обычной мапой, мы можем получать по отдельности упорядоченные ключи, значения или коллекцию Map.Entry, которая также поддерживает порядок.

SequencedMap<String, Integer> map = new TreeMap<>();
map.put("bbb", 456);
map.put("ccc", 789);
map.put("aaa", 123);
System.out.println(map.sequencedKeySet()); // [aaa, bbb, ccc]
System.out.println(map.sequencedValues()); // [123, 456, 789]
System.out.println(map.sequencedEntrySet()); // [aaa=123, bbb=456, ccc=789]

Методы sequencedKeySet() и sequencedEntrySet() возвращают упорядоченные множества SequencedSet. Метод sequencedValues() возвращает упорядоченный список SequencedCollection.

Итоги

Мы рассмотрели особенности интерфейса SequencedMap и убедились, что концептуально он похож на SequencedCollection. При этом два интерфейса не связаны напрямую иерархией наследования. SequencedMap предоставляет удобный набор методов для работы с упорядоченными ключами и значениями мапы.


Облако тэгов

Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.

Последние статьи


Комментарии

Добавить комментарий

×

devmark.ru