Статьи
Утилиты 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 предоставляет удобный набор методов для работы с упорядоченными ключами и значениями мапы.



Комментарии

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

×

devmark.ru