Эффективный способ итерации по каждой записи в Java Map?
Если у меня есть объект, реализующий интерфейс Map
в Java, и я хочу пройтись по каждой паре, содержащейся в нем, каков самый эффективный способ перебора элементов карты?
Зависит ли порядок элементов от конкретной реализации карты, которую я использую для этого интерфейса?
4 ответ(ов)
Если вы хотите вывести ключи и значения из Map
в Java, вы можете использовать следующий код:
Для версий Java до 10:
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Для Java 10 и выше вы можете использовать var
для упрощения записи:
for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Оба примера кода делают одно и то же: они перебирают все записи (пары ключ-значение) в вашем Map
и выводят их в формате ключ/значение
. В версии с var
код становится более лаконичным, но сохраняет ту же логику.
В Java 8 вы можете сделать это просто и быстро, используя новые возможности лямбд:
Map<String, String> map = new HashMap<>();
map.put("SomeKey", "SomeValue");
map.forEach((k, v) -> [сделать что-то с ключом и значением]);
// Например
map.forEach((k, v) -> System.out.println("Ключ: " + k + ": Значение: " + v));
Типы k
и v
будут выведены компилятором, и больше нет необходимости использовать Map.Entry
.
Просто и удобно!
Типичный код для перебора карты в Java выглядит следующим образом:
Map<String, Thing> map = ...;
for (Map.Entry<String, Thing> entry : map.entrySet()) {
String key = entry.getKey();
Thing thing = entry.getValue();
...
}
HashMap
является канонической реализацией карты и не дает гарантий упорядоченности (хотя порядок не должен изменяться, если не производить мутационных операций). SortedMap
возвращает элементы на основе естественного порядка ключей или по заданному компаратору. LinkedHashMap
возвращает элементы в порядке вставки или в порядке доступа, в зависимости от того, как он был создан. EnumMap
возвращает элементы в естественном порядке ключей.
(Обновление: Я думаю, что это больше не так.) Обратите внимание, что итератор entrySet
в IdentityHashMap
в настоящее время имеет своеобразную реализацию, которая возвращает один и тот же экземпляр Map.Entry
для каждого элемента в entrySet
! Однако каждый раз, когда новый итератор продвигается, Map.Entry
обновляется.
Пример использования итератора и дженериков в Java можно увидеть в следующем коде:
Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
// ... обработка ключа и значения
}
В этом примере мы получаем итератор для набора пар "ключ-значение" из Map
. Затем с помощью цикла while
перебираем каждую запись, извлекая ключи и значения. Это демонстрирует использование дженериков (в данном случае Map.Entry<String, String>
) для обеспечения безопасного доступа к типам данных в коллекции.
Итерация по коллекции: избегаем ConcurrentModificationException при удалении объектов в цикле
Как инициализировать статическую Map?
Сортировка Map<Key, Value> по значениям
Как напрямую инициализировать HashMap (в литеральном виде)?
Разница между HashMap, LinkedHashMap и TreeMap