8 ноября 2023
Тэги: Collections, Java, ООП.
В статье SequencedCollection и SequencedSet в Java мы рассмотрели интерфейс SequencedCollection, который появился в Java 21. Также узнали про его более частный случай – интерфейс SequencedSet.
Теперь перейдём к интерфейсу SequencedMap, который обладает сходным функционалом, но не входит напрямую в иерархию SequencedCollection.
Этот интерфейс расширяет стандартный Map, добавляя в него методы для доступа и манипулирования первым и последним элементами. В отличие от SequencedCollection, здесь мы манипулируем не отдельными значениями, а сразу парой «ключ-значение», представленной Map.Entry.
Помимо этого, мы можем отдельно получать множество упорядоченных ключей и упорядоченных значений. Ну и уже привычный нам метод reversed(), который позволяет обходить мапу в обратном порядке.
По аналогии с SequencedSet, интерфейс SequencedMap поддерживается классами LinkedHashMap и TreeMap. При этом HashMap не поддерживает интерфейс SequencedMap, потому что изначально не гарантирует порядок.
Упрощённая иерархия классов и интерфейсов, связанных с SequencedMap, представлена на этой схеме:
Если мы возьмём за основу LinkedHashMap, то метод putLast(), добавляющий элемент в конец мапы, будет действовать аналогично стандартному put(), т.к. данный вид мапы сохраняет порядок добавления. В начало мапы в любой момент можно добавить с помощью putFirst().
Для вывода содержимого мапы в обратном порядке используем метод reversed().
Класс TreeMap хоть и поддерживает интерфейс SequencedMap, но не поддерживает методы добавления первого и последнего элемента, т.к. этот вид мапы всегда сортирует ключи в алфавитном порядке, а потому сам «знает», какой элемент должен быть «первым», а какой – «последним».
При попытке вызвать метод putFirst() или putLast() мы получим UnsupportedOperationException. Поэтому в TreeMap добавление элементов делаем через старый добрый put().
Удаление элементов мы делаем с помощью методов pollFirstEntry() и pollLastEntry(). Они удаляют элемент из мапы и возвращают его в качестве результата. Если мапа будет пустая, они не кидают ошибку и просто возвращают null.
И здесь особой разницы между LinkedHashMap и TreeMap нет, поскольку для TreeMap тоже всегда известен «первый» и «последний» элемент.
Для получения первого и последнего элементы мы используем методы getFirstEntry() и getLastEntry().
Если мапа пустая, методы будут возвращает null так же, как и при удалении. Поэтому разницы между LinkedHashMap и TreeMap здесь нет.
Как и в случае с обычной мапой, мы можем получать по отдельности упорядоченные ключи, значения или коллекцию Map.Entry, которая также поддерживает порядок.
Методы sequencedKeySet() и sequencedEntrySet() возвращают упорядоченные множества SequencedSet. Метод sequencedValues() возвращает упорядоченный список SequencedCollection.
Мы рассмотрели особенности интерфейса SequencedMap и убедились, что концептуально он похож на SequencedCollection. При этом два интерфейса не связаны напрямую иерархией наследования. SequencedMap предоставляет удобный набор методов для работы с упорядоченными ключами и значениями мапы.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.