1. Обзор
Мы часто используем карты для хранения набора пар ключ-значение. Затем, в какой-то момент, нам часто нужно перебирать их .
В этом руководстве мы сравним различные методы итерации карты, выделив, когда может быть полезно использовать Map.Entry
. Затем мы узнаем, как можно использовать Map.Entry для создания кортежа.
Наконец, мы создадим упорядоченный список кортежей.
2. Оптимизация итерации карты
Предположим, что у нас есть карта названий книг с именем автора в качестве ключа:
Map<String, String> map = new HashMap<>();
map.put("Robert C. Martin", "Clean Code");
map.put("Joshua Bloch", "Effective Java");
Давайте сравним два метода получения всех ключей и значений из нашей карты.
2.1. Использование Map.keySet
Во-первых, рассмотрите следующее:
for (String key : bookMap.keySet()) {
System.out.println("key: " + key + " value: " + bookMap.get(key));
}
Здесь цикл перебирает набор ключей
. Для каждого ключа мы получаем соответствующее значение с помощью Map.get
. Хотя это очевидный способ использовать все записи на карте, для каждой записи требуется две операции — одна для получения следующего ключа и одна для поиска значения с помощью get
.
Если нам нужны только ключи на карте, keySet
— хороший вариант. Однако есть более быстрый способ получить как ключи, так и значения.
2.2. Использование Map.entrySet
вместо этого
Давайте перепишем нашу итерацию, чтобы использовать entrySet
:
for (Map.Entry<String, String> book: bookMap.entrySet()) {
System.out.println("key: " + book.getKey() + " value: " + book.getValue());
}
В этом примере наш цикл проходит по коллекции объектов Map.Entry
. Поскольку Map.Entry
хранит и ключ, и значение вместе в одном классе, мы получаем их оба в одной операции .
Те же правила применяются к использованию потоковых операций Java 8 . Потоковая передача через entrySet
и работа с объектами Entry
более эффективны и могут потребовать меньше кода.
3. Работа с кортежами
Кортеж — это структура данных с фиксированным количеством и порядком элементов. Мы можем думать о Map.Entry
как о кортеже, который хранит два элемента — ключ и значение. Однако, поскольку Map.Entry
— это интерфейс, нам требуется класс реализации. В этом разделе мы рассмотрим одну реализацию, предоставляемую JDK: AbstractMap.SimpleEntry
.
3.1. Создание кортежа
Сначала рассмотрим класс Book :
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
...
Далее создадим кортеж Map.Entry
с ISBN в качестве ключа и объектом Book
в качестве значения:
Map.Entry<String, Book> tuple;
Наконец, давайте создадим экземпляр нашего кортежа с помощью AbstractMap.SimpleEntry
:
tuple = new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch"));
3.2. Создание упорядоченного списка кортежей
При работе с кортежами часто полезно иметь их в виде упорядоченного списка.
Во-первых, мы определим наш список кортежей:
List<Map.Entry<String, Book>> orderedTuples = new ArrayList<>();
Во-вторых, давайте добавим несколько записей в наш список:
orderedTuples.add(new AbstractMap.SimpleEntry<>("9780134685991",
new Book("Effective Java 3d Edition", "Joshua Bloch")));
orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884",
new Book("Clean Code","Robert C Martin")));
3.3. Сравнение с картой
Чтобы сравнить различия с Map
, давайте добавим новую запись с уже существующим ключом:
orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884",
new Book("Clean Code", "Robert C Martin")));
Во-вторых, мы пройдемся по нашему списку, отображая все ключи и значения:
for (Map.Entry<String, Book> tuple : orderedTuples) {
System.out.println("key: " + tuple.getKey() + " value: " + tuple.getValue());
}
Наконец, давайте посмотрим на вывод:
key: 9780134685991 value: Book{title='Effective Java 3d Edition', author='Joshua Bloch'}
key: 9780132350884 value: Book{title='Clean Code', author='Robert C Martin'}
key: 9780132350884 value: Book{title='Clean Code', author='Robert C Martin'}
Обратите внимание, что у нас могут быть повторяющиеся ключи, в отличие от базовой карты
, где каждый ключ должен быть уникальным. Это связано с тем, что мы использовали реализацию List
для хранения наших объектов SimpleEntry
, что означает, что все объекты независимы друг от друга.
3.4. Списки объектов входа
Следует отметить, что Entry
не предназначен для использования в качестве универсального кортежа. Классы библиотеки часто предоставляют для этой цели универсальный `` класс Pair .
Однако мы можем обнаружить, что нам нужно временно работать со списками записей при подготовке данных для Карты
или извлечении данных из нее.
4. Вывод
В этой статье мы рассмотрели Map.entrySet
как альтернативу перебору ключей карты.
Затем мы рассмотрели, как Map.Entry
можно использовать в качестве кортежа.
Наконец, мы создали список упорядоченных кортежей, сравнивая различия с базовой картой
.
Как всегда, код примера доступен на GitHub .