Как мне эффективно перебирать каждую запись в Java Map?

Если у меня есть объект, реализующий интерфейс Map на Java, и я хочу перебрать каждую содержащуюся в нем пару, каков наиболее эффективный способ просмотра карты?

Будет ли порядок элементов зависеть от конкретной реализации карты, которая у меня есть для интерфейса?

В Java 8 с использованием лямбда-выражения: stackoverflow.com/a/25616206/1503859

Nitin Mahesh 25.07.2015 21:31

Java 8: stackoverflow.com/questions/46898/…

akhil_mittal 10.10.2018 15:45
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3 502
2
2 655 651
45
Перейти к ответу Данный вопрос помечен как решенный

Ответы 45

Да, порядок зависит от конкретной реализации карты.

@ ScArcher2 имеет более элегантный синтаксис Java 1.5.. В 1.4 я бы сделал что-то вроде этого:

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}

Предпочитайте цикл for, чем while .. for (Iterator entries = myMap.entrySet (). Iterator (); entries.hasNext ();) {...} Благодаря этому синтаксису область 'записей' сокращается только до цикла for .

jai 20.10.2009 17:20

@jpredham Вы правы в том, что использование конструкции for в качестве for (Entry e : myMap.entrySet) не позволит вам изменять коллекцию, но в примере @HanuAthena упоминается, что она должна работать, поскольку дает вам Iterator в области видимости. (Если я чего-то не упускаю ...)

pkaeding 10.01.2012 19:42

IntelliJ выдает ошибки на Entry thisEntry = (Entry) entries.next();: не распознает Entry. Этот псевдокод для чего-то другого?

JohnK 10.01.2015 03:06

@JohnK попробуйте импортировать java.util.Map.Entry.

pkaeding 14.01.2015 05:35

Это решение не будет работать, если у вас есть целочисленный ключ и строковый ключ.

user5778069 21.01.2017 11:09
Ответ принят как подходящий

Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

Если вы это сделаете, это не сработает, поскольку Entry является вложенным классом в Map. java.sun.com/javase/6/docs/api/java/util/Map.html

ScArcher2 22.03.2010 16:30

вы можете записать импорт как «import java.util.Map.Entry;» и это будет работать.

jjujuma 30.04.2010 14:34

@Pureferret Единственная причина, по которой вы можете захотеть использовать итератор, - это вызов его метода remove. Если это так, этот другой ответ покажет вам, как это сделать. В противном случае лучше использовать расширенный цикл, показанный в ответе выше.

assylias 08.10.2012 14:34

Я считаю, что форма Map.Entry более понятна, чем импорт внутреннего класса в текущее пространство имен.

Josiah Yoder 04.12.2014 23:31

где объявлена ​​карта из map.entrySet ()?

Saras Arya 06.04.2015 14:19

Быстрый вопрос: должны ли общие значения <String, String> соответствовать значению карты? Например, у меня <String, Foo>.

Fallenreaper 22.06.2015 16:10

Конечно, предполагается, что ваш Map называется map. Новички могут не понять.

intcreator 28.09.2015 23:28

@brandaemon Согласен. Даже для промежуточных звеньев приятно видеть, какой именно тип реализует метод entrySet.

jpaugh 26.01.2016 23:38

Обратите внимание, что вы можете использовать map.values() или map.keySet(), если хотите перебирать только значения или ключи.

dguay 13.10.2016 00:03

Это неэффективно. Карта содержит данные в наборе записей. Для скорости всегда перебирайте набор записей.

Marcus MacWilliam 13.02.2018 18:15

Я получаю ошибку несовместимых типов для записи «Map.Entry entry» и «Map.Entry <Integer, HashMap>»: «Требуемый объект, найдена запись». Я сопоставляю целые числа с хэш-картами. Из-за этого необходимо использовать набор ключей для цикла и вытащить значение через 'value = (HashMap) integertomap.get (key)', хотя и менее эффективно, чем если бы я мог использовать entrySet без итератора в соответствии с вашим примером.

Androidcoder 25.07.2018 19:44

@MarcusMacWilliam «Карта содержит данные в наборе записей» - это неверно для многих реализаций Map. См., Например, реализацию TreeMap, которая просматривает дерево для ключей, значений или записей.

JimmyB 14.11.2018 17:09

@ ScArcher2 Нет, это не так. Это вложенный интерфейс, и даже если бы это был вложенный c, он все равно работал бы. Этот код работает. Использовал. Этому на 15 лет. Импорт не требуется.

user207421 14.02.2019 12:43

Теоретически наиболее эффективный способ будет зависеть от того, какая реализация Map. Официальный способ сделать это - вызвать map.entrySet(), который возвращает набор Map.Entry, каждый из которых содержит ключ и значение (entry.getKey() и entry.getValue()).

В идиосинкразической реализации может иметь значение, используете ли вы map.keySet(), map.entrySet() или что-то еще. Но я не могу придумать причину, по которой кто-то мог бы написать это так. Скорее всего, для производительности не имеет значения то, что вы делаете.

И да, порядок будет зависеть от реализации, а также (возможно) порядка вставки и других факторов, которые трудно контролировать.

[править] Первоначально я написал valueSet(), но, конечно же, entrySet() - это ответ.

Типичный код для итерации по карте:

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap является реализацией канонической карты и не дает гарантий (или хотя он не должен изменять порядок, если с ним не выполняются операции изменения). SortedMap будет возвращать записи на основе естественного порядка ключей или Comparator, если он предоставлен. LinkedHashMap будет возвращать записи либо в порядке вставки, либо в порядке доступа, в зависимости от того, как он был построен. EnumMap возвращает записи в естественном порядке ключей.

(Обновление: я думаю, что это уже не так.) Обратите внимание: итератор IdentityHashMapentrySet в настоящее время имеет особую реализацию, которая возвращает один и тот же экземпляр Map.Entry для каждого элемента в entrySet! Однако каждый раз, когда новый итератор продвигается, Map.Entry обновляется.

EnumMap также имеет это своеобразное поведение вместе с IdentityHashMap.

Premraj 10.03.2011 18:41

«LinkedHashMap будет либо возвращать записи в [...] порядке доступа [...]» ... чтобы вы обращались к элементам в порядке доступа к ним? Либо тавтологическое, либо что-то интересное, в котором можно сделать отступление. ;-)

jpaugh 26.01.2016 23:41

@jpaugh Только прямой доступ к счетчику LinkedHashMap. Посылки через iterator, spliterator, entrySet и т. д. Не изменяют порядок.

Tom Hawtin - tackline 27.01.2016 00:24

1. хотяесли? 2. Последний абзац можно улучшить.

Peter Mortensen 07.02.2018 01:36

Это вопрос из двух частей:

Как перебирать записи на карте - @ ScArcher2 отлично имеет ответил.

Каков порядок итерации - если вы просто используете Map, то, строго говоря, есть нет гарантии заказа. Таким образом, вам не следует полагаться на порядок, заданный какой-либо реализацией. Однако интерфейс SortedMap расширяет Map и предоставляет именно то, что вы ищете - реализации всегда будут давать согласованный порядок сортировки.

NavigableMap - еще одно полезное расширение - это SortedMap с дополнительными методами поиска записей по их упорядоченной позиции в наборе ключей. Таким образом, потенциально это может в первую очередь избавить от необходимости повторения - вы сможете найти конкретный entry после использования методов higherEntry, lowerEntry, ceilingEntry или floorEntry. Метод descendingMap даже дает вам явный метод изменение порядка обхода.

К вашему сведению, вы также можете использовать map.keySet() и map.values(), если вас интересуют только ключи / значения карты, а не другие.

Правильный способ сделать это - использовать принятый ответ, так как он наиболее эффективен. Я считаю, что следующий код выглядит немного чище.

for (String key: map.keySet()) {
   System.out.println(key + "/" + map.get(key));
}

Это не лучший подход, гораздо эффективнее использовать entrySet (). Findbugs отметит этот код (см. findbugs.sourceforge.net/…)

Jeff Olson 06.11.2009 23:46

@ ДжеффОлсон, да, не совсем. поиск по карте - O (1), поэтому оба цикла ведут себя одинаково. по общему признанию, это будет немного медленнее в микробенчмарке, но я иногда делаю это, потому что ненавижу писать аргументы типа снова и снова. Кроме того, это, скорее всего, никогда не будет узким местом для вашей производительности, поэтому сделайте это, если это сделает код более читабельным.

kritzikratzi 08.10.2012 17:25

@kritzikratzi, но с подходом entrySet () вы выполняете один поиск для каждого элемента, тогда как с подходом keySet () / get () вы выполняете два поиска для каждого элемента. Итак, теоретически (не тестировал) это O (1) против 2 * O (1). Или вдвое дольше. Правильно?

Jeff Olson 08.10.2012 21:34

подробнее: O(1) = 2*O(1) - это в значительной степени определение нотации большой буквы О. вы правы в том, что он работает немного медленнее, но по сложности они такие же.

kritzikratzi 09.10.2012 03:26

Поищите на карте O (1), правда?))))) Где на Земле это O (1)?))) HashMap: во-первых - вы должны вычислить хеш, во-вторых - искать в массиве по хешу, в-третьих! - линейный поиск по всем элементам, имеющим одинаковый хэш-код, это называется «столкновение», разве вы не слышали об этом? =) А что вы можете сказать о: TreeMap, ConcurrentSkipListMap они тоже «O (1)»?

kornero 03.12.2012 14:43

@kornero хорошая точка, поиск по древовидной карте - O (log n), я имел в виду только хэш-карты (которые ~ O (1), коллизии или нет)

kritzikratzi 22.12.2012 16:29

Коллизии @kritzikratzi в хэш-картах создают сложность ~ O (n), и на основе этого есть "отказ в обслуживании через алгоритмические атаки сложности", вы можете узнать больше об этом здесь: cs.rice.edu/~scrosby/hash/CrosbyWallach_UsenixSec2003

kornero 23.12.2012 18:30

Под столкновением я имел в виду, что не имеет значения, есть ли у вас несколько столкновений, очевидно, это другая история, если у вас есть только столкновения. Итак, вы ведете себя довольно мелочно, но да, то, что вы говорите, правда.

kritzikratzi 23.12.2012 20:17

@ Джефф Олсон: комментарии о том, что сложность «большого О» не меняется, когда есть только постоянный коэффициент, верны. Тем не менее, для меня важно, займет ли операция час или два. Что еще более важно, необходимо подчеркнуть, что коэффициент равен нет2, поскольку итерация по entrySet() вообще не требует поиска; это просто линейный обход всех записей. Напротив, итерация по keySet() и выполнение поиска по каждому ключу требует поиска один для каждого ключа, поэтому здесь мы говорим о нулевых поисках по сравнению с поисками п, где п - это размер Map. Так что фактор выходит далеко за рамки 2

Holger 09.11.2016 15:22

@kornero: стоит отметить, что вам не нужны ключи с одинаковым хэш-кодом для коллизии; коллизия уже есть, когда hashcode % capacity такой же. Начиная с Java 8, сложность элементов, имеющих один и тот же hashcode % capacity, но другой hashcode или Comparable, возвращается к O(log n), и только ключи с одинаковым хэш-кодом, не являющиеся Comparable, создают сложность O(n). Но утверждение, что на практике сложность поиска может быть больше, чем O(1), остается в силе.

Holger 09.11.2016 15:35

Пример использования итератора и дженериков:

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();
  // ...
}

Вы должны поместить Iterator в цикл for, чтобы ограничить его область действия.

Steve Kuo 18.02.2012 00:32

@SteveKuo Что вы имеете в виду, говоря «ограничить сферу охвата»?

StudioWorks 03.02.2015 19:13

@StudioWorks for (Iterator<Map.Entry<K, V>> entries = myMap.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<K, V> entry = entries.next(); }. Используя эту конструкцию, мы ограничиваем область видимости entries (видимость переменной) циклом for.

ComFreek 13.03.2015 19:33

@ComFreek Понятно. Не знал, что это так важно.

StudioWorks 13.03.2015 19:59

Попробуйте это с Java 1.4:

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

  Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() + "/" + entry.getValue());

  //...
}

public class abcd{
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Integer key:testMap.keySet()) {
            String value=testMap.get(key);
            System.out.println(value);
        }
    }
}

ИЛИ ЖЕ

public class abcd {
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Entry<Integer, String> entry : testMap.entrySet()) {
            Integer key=entry.getKey();
            String value=entry.getValue();
        }
    }
}

С Коллекции Eclipse вы должны использовать метод forEachKeyValue в интерфейсе MapIterable, который наследуется интерфейсами MutableMap и ImmutableMap и их реализациями.

MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue((key, value) -> result.add(key + value));
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

Используя анонимный внутренний класс, вы можете написать код следующим образом:

final MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue(new Procedure2<Integer, String>()
{
    public void value(Integer key, String value)
    {
        result.add(key + value);
    }
});
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

Примечание: Я участник коллекций Eclipse.

Да, как многие согласились, это лучший способ перебрать Map.

Но есть шансы скинуть nullpointerexception, если карта null. Не забудьте поставить null. Check in.

                                                 |
                                                 |
                                         - - - -
                                       |
                                       |
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
}

Вы можете сделать это с помощью дженериков:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

В Java 8 вы можете сделать это чисто и быстро, используя новые функции лямбда-выражений:

 Map<String,String> map = new HashMap<>();
 map.put("SomeKey", "SomeValue");
 map.forEach( (k,v) -> [do something with key and value] );

 // such as
 map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));

Типы k и v будут определены компилятором, и больше нет необходимости использовать Map.Entry.

Очень просто!

В зависимости от того, что вы хотите делать с картой, вы также можете использовать потоковый API для записей, возвращаемых map.entrySet().stream()docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.ht‌ ml

Vitalii Fedorenko 28.06.2014 16:46

Это не сработает, если вы хотите ссылаться на неокончательные переменные, объявленные вне вашего лямбда-выражения, из forEach () ...

Chris 20.04.2017 23:29

@ Крис Верно. Это не сработает, если вы попытаетесь использовать переменные фактически не окончательный извне лямбда.

The Coordinator 22.04.2017 00:44

Если у вас есть общая нетипизированная карта, вы можете использовать:

Map map = new HashMap();
for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

Есть несколько способов перебрать карту. См. Следующий код.

Когда вы повторяете карту с использованием интерфейса итератора, вы должны использовать Entry<K,V> или entrySet().

Это выглядит так:

    import java.util.*;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;

    public class IteratMapDemo{

        public static void main(String arg[]){
            Map<String, String> mapOne = new HashMap<String, String>();
            mapOne.put("1", "January");
            mapOne.put("2", "February");
            mapOne.put("3", "March");
            mapOne.put("4", "April");
            mapOne.put("5", "May");
            mapOne.put("6", "June");
            mapOne.put("7", "July");
            mapOne.put("8", "August");
            mapOne.put("9", "September");
            mapOne.put("10", "Octomber");
            mapOne.put("11", "November");
            mapOne.put("12", "December");

            Iterator it = mapOne.entrySet().iterator();
            while(it.hasNext())
            {
                Map.Entry me = (Map.Entry) it.next();
                //System.out.println("Get Key through While loop = " + me.getKey());
            }
            for(Map.Entry<String, String> entry:mapOne.entrySet()){
                //System.out.println(entry.getKey() + " = " + entry.getValue());
            }

            for (Object key : mapOne.keySet()) {
                System.out.println("Key: " + key.toString() + " Value: " +
                                   mapOne.get(key));
            }
        }
    }

keySet () работает медленно

edin-m 29.11.2019 06:38

В Map можно выполнять итерацию по keys и / или values и / или both (e.g., entrySet), в зависимости от того, что вас интересует.

  1. Перебрать keys -> keySet() карты:

     Map<String, Object> map = ...;
    
     for (String key : map.keySet()) {
         //your Business logic...
     }
    
  2. Перебрать values -> values() карты:

     for (Object value : map.values()) {
         //your Business logic...
     }
    
  3. Перебрать both -> entrySet() карты:

     for (Map.Entry<String, Object> entry : map.entrySet()) {
         String key = entry.getKey();
         Object value = entry.getValue();
         //your Business logic...
     }
    

Более того, есть 3 разных способа итерации через HashMap. Они такие, как показано ниже:

//1.
for (Map.Entry entry : hm.entrySet()) {
    System.out.print("key,val: ");
    System.out.println(entry.getKey() + "," + entry.getValue());
}

//2.
Iterator iter = hm.keySet().iterator();
while(iter.hasNext()) {
    Integer key = (Integer)iter.next();
    String val = (String)hm.get(key);
    System.out.println("key,val: " + key + "," + val);
}

//3.
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry entry = (Map.Entry) it.next();
    Integer key = (Integer)entry.getKey();
    String val = (String)entry.getValue();
    System.out.println("key,val: " + key + "," + val);
}

Есть несколько способов перебрать карту.

Вот сравнение их производительности для общего набора данных, хранящегося в карте, путем сохранения миллиона пар ключевых значений в карте и повторения по карте.

1) Использование entrySet() для каждого цикла

for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
    entry.getKey();
    entry.getValue();
}

50 миллисекунд

2) Использование keySet() для каждого цикла

for (String key : testMap.keySet()) {
    testMap.get(key);
}

76 миллисекунд

3) Использование entrySet() и итератора

Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()) {
    Map.Entry<String,Integer> entry = itr1.next();
    entry.getKey();
    entry.getValue();
}

50 миллисекунд

4) Использование keySet() и итератора

Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
    String key = itr2.next();
    testMap.get(key);
}

75 миллисекунд

Я сослался на this link.

Время выполнения взято из статьи, в которой не используется Java Microbenchmarking Harness. Поэтому время ненадежно, так как код мог, например, быть полностью оптимизирован JIT-компилятором.

AlexB 14.01.2019 16:44

    Iterator iterator = map.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry element = (Map.Entry)it.next();
        LOGGER.debug("Key: " + element.getKey());
        LOGGER.debug("value: " + element.getValue());    
    }

Java 8:

Вы можете использовать лямбда-выражения:

myMap.entrySet().stream().forEach((entry) -> {
    Object currentKey = entry.getKey();
    Object currentValue = entry.getValue();
});

Для получения дополнительной информации следуйте это.

@injecteer: Похоже, мотив лямбда-выражений

humblerookie 21.08.2014 23:49

Вам не нужен поток, если вы просто хотите перебирать карту. myMap.forEach( (currentKey,currentValue) -> /* action */ ); намного лаконичнее.

Holger 09.11.2016 15:37

Я скопировал данные карты на другую с помощью этого кода:

HashMap product =(HashMap)shopping_truck.get(i);
HashMap tmp = new HashMap();
for (Iterator it = product.entrySet().iterator(); it.hasNext();) {
    Map.Entry thisEntry = (Map.Entry) it.next();
    tmp.put(thisEntry.getKey(), thisEntry.getValue());
}

Он не совсем отвечает на вопрос OP, но может быть полезен другим, кто найдет эту страницу:

Если вам нужны только значения, а не ключи, вы можете сделать это:

Map<Ktype, Vtype> myMap = [...];
for (Vtype v: myMap.values()) {
  System.out.println("value: " + v);
}

Ktype, Vtype - это псевдокод.

Вот общий типобезопасный метод, который можно вызвать для сброса любого заданного Map.

import java.util.Iterator;
import java.util.Map;

public class MapUtils {
    static interface ItemCallback<K, V> {
        void handler(K key, V value, Map<K, V> map);
    }

    public static <K, V> void forEach(Map<K, V> map, ItemCallback<K, V> callback) {
        Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();

        while (it.hasNext()) {
            Map.Entry<K, V> entry = it.next();

            callback.handler(entry.getKey(), entry.getValue(), map);
        }
    }

    public static <K, V> void printMap(Map<K, V> map) {
        forEach(map, new ItemCallback<K, V>() {
            @Override
            public void handler(K key, V value, Map<K, V> map) {
                System.out.println(key + " = " + value);
            }
        });
    }
}

Пример

Вот пример его использования. Обратите внимание, что тип Map определяется методом.

import java.util.*;

public class MapPrinter {
    public static void main(String[] args) {
        List<Map<?, ?>> maps = new ArrayList<Map<?, ?>>() {
            private static final long serialVersionUID = 1L;
            {
                add(new LinkedHashMap<String, Integer>() {
                    private static final long serialVersionUID = 1L;
                    {
                        put("One", 0);
                        put("Two", 1);
                        put("Three", 3);
                    }
                });

                add(new LinkedHashMap<String, Object>() {
                    private static final long serialVersionUID = 1L;
                    {
                        put("Object", new Object());
                        put("Integer", new Integer(0));
                        put("Double", new Double(0.0));
                    }
                });
            }
        };

        for (Map<?, ?> map : maps) {
            MapUtils.printMap(map);
            System.out.println();
        }
    }
}

Выход

One = 0
Two = 1
Three = 3

Object = java.lang.Object@15db9742
Integer = 0
Double = 0.0

Я считаю, что это самый простой способ сделать это ...

/* For example, this could be a map object */
Map<String, Integer> MAP = new Map<>();

// Do something like put keys/value pairs into the map, etc...
MAP.put("Denver", 35);
MAP.put("Patriots", 14);

/* Then, simply use a for each loop like this to iterate */
for (Object o : MAP.entrySet()) {
    Map.Entry pair = (Map.Entry) o;
    // Do whatever with the pair here (i.e. pair.getKey(), or pair.getValue();
}

Если ваша причина для итерации через Map, заключается в том, чтобы выполнить операцию со значением и записать в полученный Map. Рекомендую использовать transform-методы в классе Google GuavaMaps.

import com.google.common.collect.Maps;

После того, как вы добавили Maps в свой импорт, вы можете использовать Maps.transformValues и Maps.transformEntries на своих картах, например:

public void transformMap(){
    Map<String, Integer> map = new HashMap<>();
    map.put("a", 2);
    map.put("b", 4);

    Map<String, Integer> result = Maps.transformValues(map, num -> num * 2);
    result.forEach((key, val) -> print(key, Integer.toString(val)));
    // key=a,value=4
    // key=b,value=8

    Map<String, String> result2 = Maps.transformEntries(map, (key, value) -> value + "[" + key + "]");
    result2.forEach(this::print);
    // key=a,value=2[a]
    // key=b,value=4[b]
}

private void print(String key, String val){
    System.out.println("key = " + key + ",value = " + val);
}

Java 8

У нас есть метод forEach, который принимает лямбда-выражение. У нас также есть API транслировать. Рассмотрим карту:

Map<String,String> sample = new HashMap<>();
sample.put("A","Apple");
sample.put("B", "Ball");

Перебрать ключи:

sample.keySet().forEach((k) -> System.out.println(k));

Перебрать значения:

sample.values().forEach((v) -> System.out.println(v));

Итерировать записи (с использованием forEach и Streams):

sample.forEach((k,v) -> System.out.println(k + ":" + v)); 
sample.entrySet().stream().forEach((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + ":" + currentValue);
        });

Преимущество потоков в том, что их можно легко распараллелить, если мы захотим. Нам просто нужно использовать parallelStream() вместо stream(), описанного выше.

forEachOrdered против forEach с потоками?forEach не следует порядку обнаружения (если он определен) и по своей сути недетерминирован по своей природе, в отличие от forEachOrdered. Таким образом, forEach не гарантирует соблюдение порядка. Также проверьте это для получения дополнительной информации.

Lambda Expression Java 8

В Java 1.8 (Java 8) это стало намного проще благодаря использованию метода для каждого из Aggregate operations (Потоковые операции), который похож на итераторы из интерфейса Итерабельный.

Просто скопируйте инструкцию вставки ниже в свой код и переименуйте переменную HashMap из хм в свою переменную HashMap, чтобы распечатать пару ключ-значение.

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
 *     Logic to put the Key,Value pair in your HashMap hm
 */

// Print the key value pair in one line.

hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

// Just copy and paste above line to your code.

Ниже приведен пример кода, который я пробовал использовать Лямбда-выражение. Это так здорово. Должен попробовать.

HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
    Random rand = new Random(47);
    int i = 0;
    while(i < 5) {
        i++;
        int key = rand.nextInt(20);
        int value = rand.nextInt(50);
        System.out.println("Inserting key: " + key + " Value: " + value);
        Integer imap = hm.put(key, value);
        if ( imap == null) {
            System.out.println("Inserted");
        } else {
            System.out.println("Replaced with " + imap);
        }               
    }

    hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

Output:

Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

Также для этого можно использовать Spliterator.

Spliterator sit = hm.entrySet().spliterator();

ОБНОВИТЬ


Включая ссылки на документацию Oracle Docs. Для получения дополнительной информации о Лямбда перейдите к этому связь и должны прочитать Агрегированные операции, а для Spliterator перейдите к этому связь.

Если вы хотите перебрать карту в том порядке, в котором были добавлены элементы, используйте LinkedHashMap, а не только Map.

Этот подход работал у меня в прошлом:

LinkedHashMap<String,Integer> test=new LinkedHashMap();

test.put("foo",69);
test.put("bar",1337);

for(int i=0;i<test.size();i++){
    System.out.println(test.get(test.keySet().toArray()[i]));
}

Выход:

69
1337

Чтобы обобщить другие ответы и объединить их с тем, что я знаю, я нашел 10 основных способов сделать это (см. Ниже). Также я написал несколько тестов производительности (см. Результаты ниже). Например, если мы хотим найти сумму всех ключей и значений карты, мы можем написать:

  1. Использование итератор и Map.Entry

    long i = 0;
    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Integer, Integer> pair = it.next();
        i += pair.getKey() + pair.getValue();
    }
    
  2. Использование для каждого и Map.Entry

    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
    
  3. Использование для каждого из Java 8

    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
    
  4. Использование keySet и для каждого

    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
    
  5. Использование keySet и итератор

    long i = 0;
    Iterator<Integer> itr2 = map.keySet().iterator();
    while (itr2.hasNext()) {
        Integer key = itr2.next();
        i += key + map.get(key);
    }
    
  6. Использование за и Map.Entry

    long i = 0;
    for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
        Map.Entry<Integer, Integer> entry = entries.next();
        i += entry.getKey() + entry.getValue();
    }
    
  7. Использование Java 8 Stream API

    final long[] i = {0};
    map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  8. Использование Java 8 Параллельный Stream API

    final long[] i = {0};
    map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  9. Использование IterableMapApache Collections

    long i = 0;
    MapIterator<Integer, Integer> it = iterableMap.mapIterator();
    while (it.hasNext()) {
        i += it.next() + it.getValue();
    }
    
  10. Использование MutableMap коллекций Eclipse (CS)

    final long[] i = {0};
    mutableMap.forEachKeyValue((key, value) -> {
        i[0] += key + value;
    });
    

Тесты производительности (режим = Среднее время, система = Windows 8.1 64-разрядная, Intel i7-4790 3,60 ГГц, 16  ГБ)

  1. Для маленькой карты (100 элементов) лучший результат - 0,308.

    Benchmark                          Mode  Cnt  Score    Error  Units
    test3_UsingForEachAndJava8         avgt  10   0.308 ±  0.021  µs/op
    test10_UsingEclipseMap             avgt  10   0.309 ±  0.009  µs/op
    test1_UsingWhileAndMapEntry        avgt  10   0.380 ±  0.014  µs/op
    test6_UsingForAndIterator          avgt  10   0.387 ±  0.016  µs/op
    test2_UsingForEachAndMapEntry      avgt  10   0.391 ±  0.023  µs/op
    test7_UsingJava8StreamApi          avgt  10   0.510 ±  0.014  µs/op
    test9_UsingApacheIterableMap       avgt  10   0.524 ±  0.008  µs/op
    test4_UsingKeySetAndForEach        avgt  10   0.816 ±  0.026  µs/op
    test5_UsingKeySetAndIterator       avgt  10   0.863 ±  0.025  µs/op
    test8_UsingJava8StreamApiParallel  avgt  10   5.552 ±  0.185  µs/op
    
  2. Для карты с 10000 элементами оценка 37,606 - лучшая.

    Benchmark                           Mode   Cnt  Score      Error   Units
    test10_UsingEclipseMap              avgt   10    37.606 ±   0.790  µs/op
    test3_UsingForEachAndJava8          avgt   10    50.368 ±   0.887  µs/op
    test6_UsingForAndIterator           avgt   10    50.332 ±   0.507  µs/op
    test2_UsingForEachAndMapEntry       avgt   10    51.406 ±   1.032  µs/op
    test1_UsingWhileAndMapEntry         avgt   10    52.538 ±   2.431  µs/op
    test7_UsingJava8StreamApi           avgt   10    54.464 ±   0.712  µs/op
    test4_UsingKeySetAndForEach         avgt   10    79.016 ±  25.345  µs/op
    test5_UsingKeySetAndIterator        avgt   10    91.105 ±  10.220  µs/op
    test8_UsingJava8StreamApiParallel   avgt   10   112.511 ±   0.365  µs/op
    test9_UsingApacheIterableMap        avgt   10   125.714 ±   1.935  µs/op
    
  3. Для карты со 100000 элементами лучший результат - 1184,767.

    Benchmark                          Mode   Cnt  Score        Error    Units
    test1_UsingWhileAndMapEntry        avgt   10   1184.767 ±   332.968  µs/op
    test10_UsingEclipseMap             avgt   10   1191.735 ±   304.273  µs/op
    test2_UsingForEachAndMapEntry      avgt   10   1205.815 ±   366.043  µs/op
    test6_UsingForAndIterator          avgt   10   1206.873 ±   367.272  µs/op
    test8_UsingJava8StreamApiParallel  avgt   10   1485.895 ±   233.143  µs/op
    test5_UsingKeySetAndIterator       avgt   10   1540.281 ±   357.497  µs/op
    test4_UsingKeySetAndForEach        avgt   10   1593.342 ±   294.417  µs/op
    test3_UsingForEachAndJava8         avgt   10   1666.296 ±   126.443  µs/op
    test7_UsingJava8StreamApi          avgt   10   1706.676 ±   436.867  µs/op
    test9_UsingApacheIterableMap       avgt   10   3289.866 ±  1445.564  µs/op
    

Графики (тесты производительности в зависимости от размера карты)

Enter image description here

Таблица (тесты производительности в зависимости от размера карты)

          100     600      1100     1600     2100
test10    0.333    1.631    2.752    5.937    8.024
test3     0.309    1.971    4.147    8.147   10.473
test6     0.372    2.190    4.470    8.322   10.531
test1     0.405    2.237    4.616    8.645   10.707
test2     0.376    2.267    4.809    8.403   10.910
test7     0.473    2.448    5.668    9.790   12.125
test9     0.565    2.830    5.952   13.220   16.965
test4     0.808    5.012    8.813   13.939   17.407
test5     0.810    5.104    8.533   14.064   17.422
test8     5.173   12.499   17.351   24.671   30.403

Все тесты идут на GitHub.

@Viacheslav: очень хороший ответ. Просто интересно, как API Java8 затрудняются в вашем тесте из-за захвата лямбда-выражений ... (например, long sum = 0; map.forEach( /* accumulate in variable sum*/); захватывает sum long, что может быть медленнее, например, stream.mapToInt(/*whatever*/).sum. Конечно, вы не всегда можете избежать захвата состояния, но это может быть разумное дополнение к скамейке.

GPI 12.05.2016 14:53

Ваш 8-й тест неверен. он обращается к одной и той же переменной из разных потоков без синхронизации. Чтобы решить проблему, перейдите на AtomicInteger.

talex 13.09.2016 18:20

Почему Java 8 forEach медленнее на 100000 элементов, тогда как он был самым быстрым на 100 и 10000?

ZhekaKozlov 16.03.2017 21:27

@ZhekaKozlov: посмотрите на невероятно большие значения ошибок. Учтите, что результат теста x±e подразумевает, что был результат в интервале от x-e до x+e, поэтому самый быстрый результат (1184.767±332.968) находится в диапазоне от 852 до 1518, тогда как второй самый медленный (1706.676±436.867) проходит между 1270 и 2144, поэтому результаты все равно значительно перекрываются. Теперь посмотрите на самый медленный результат, 3289.866±1445.564, который подразумевает расхождение между 1844 и 4735, а вы знать, что эти результаты тестов бессмысленны.

Holger 17.03.2017 21:28

Что насчет map.entrySet().stream().[parallel().]mapToInt(e -> e.getKey() + e.getValue()).sum();?

glglgl 05.06.2017 00:45

А как насчет сравнения трех основных реализаций: HashMap, LinkedHashMap и TreeMap?

Thierry 08.11.2017 02:37

№1 и №6 абсолютно одинаковы. Использование while по сравнению с циклом for - это не другой метод итерации. И я удивлен, что между ними есть такие различия в ваших тестах, что говорит о том, что тесты не изолированы должным образом от внешних факторов, не связанных с тем, что вы собираетесь тестировать.

ErikE 14.07.2018 22:04

для #7 используйте map + reduce, а не forEach.

njzk2 10.12.2018 08:01

#8 - ужасный пример, поскольку parallel теперь вызывает состояние гонки при добавлении к i.

Todd Sewell 02.01.2019 16:00

.stream() не нужен для forEach, поскольку он также определен в интерфейсе Iterable.

Sina Madani 26.02.2019 22:32

map.values ​​() дает набор значений в данной карте. Это может быть кому-то полезно.

Aswin Prasad 26.12.2019 05:24

Проголосовали против, потому что этот тест совершенно неработоспособен и ненадежен, как уже заметили другие комментаторы.

ciamej 11.05.2020 17:50

Эта логика не выглядит надежной, поскольку я думаю, что нет гарантии, будет ли сначала оцениваться левый или правый операнд +, а .next() может иметь побочные эффекты: i += it.next() + it.getValue()

Luke Hutchison 06.08.2020 12:10

Интересно. Однако те, в которых вы должны использовать "array-hack", чтобы избежать замыкания, могут иметь недостаток? Может быть, было интересно позволить им всем пользоваться этим? Или, может быть, даже какой-то «объект-сборщик», может быть, AtomicLong или что-то в этом роде, который не может быть легко исключен jit?

stolsvik 27.01.2021 00:59

           //Functional Oprations
            Map<String, String> mapString = new HashMap<>();
            mapString.entrySet().stream().map((entry) -> {
                String mapKey = entry.getKey();
                return entry;
            }).forEach((entry) -> {
                String mapValue = entry.getValue();
            });

            //Intrator
            Map<String, String> mapString = new HashMap<>();
            for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {
                Map.Entry<String, String> entry = it.next();
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();
            }

            //Simple for loop
            Map<String, String> mapString = new HashMap<>();
            for (Map.Entry<String, String> entry : mapString.entrySet()) {
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();

            }

Порядок всегда будет зависеть от конкретной реализации карты. Используя Java 8, вы можете использовать любое из них:

map.forEach((k,v) -> { System.out.println(k + ":" + v); });

Или же:

map.entrySet().forEach((e) -> {
            System.out.println(e.getKey() + " : " + e.getValue());
        });

Результат будет таким же (в том же порядке). EntrySet поддерживается картой, поэтому вы получаете тот же порядок. Второй удобен тем, что позволяет использовать лямбды, например если вы хотите печатать только объекты Integer, которые больше 5:

map.entrySet()
    .stream()
    .filter(e-> e.getValue() > 5)
    .forEach(System.out::println);

В приведенном ниже коде показана итерация через LinkedHashMap и обычную HashMap (пример). Вы увидите разницу в порядке:

public class HMIteration {


    public static void main(String[] args) {
        Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
        Map<Object, Object> hashMap = new HashMap<>();

        for (int i=10; i>=0; i--) {
            linkedHashMap.put(i, i);
            hashMap.put(i, i);
        }

        System.out.println("LinkedHashMap (1): ");
        linkedHashMap.forEach((k,v) -> { System.out.print(k + " (# = "+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nLinkedHashMap (2): ");

        linkedHashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });


        System.out.println("\n\nHashMap (1): ");
        hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nHashMap (2): ");

        hashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });
    }
}

Выход:

LinkedHashMap (1):
10 (#=10):10, 9 (#=9):9, 8 (#=8):8, 7 (#=7):7, 6 (#=6):6, 5 (#=5):5, 4 (#=4):4, 3 (#=3):3, 2 (#=2):2, 1 (#=1):1, 0 (#=0):0,
LinkedHashMap (2):
10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1, 0 : 0,
HashMap (1):
0 (#:0):0, 1 (#:1):1, 2 (#:2):2, 3 (#:3):3, 4 (#:4):4, 5 (#:5):5, 6 (#:6):6, 7 (#:7):7, 8 (#:8):8, 9 (#:9):9, 10 (#:10):10,
HashMap (2):
0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10,

package com.test;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Test {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("ram", "ayodhya");
        map.put("krishan", "mathura");
        map.put("shiv", "kailash");

        System.out.println("********* Keys *********");
        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key);
        }

        System.out.println("********* Values *********");
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }

        System.out.println("***** Keys and Values (Using for each loop) *****");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println("Key: " + entry.getKey() + "\t Value: "
                    + entry.getValue());
        }

        System.out.println("***** Keys and Values (Using while loop) *****");
        Iterator<Entry<String, String>> entries = map.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry<String, String>) entries
                    .next();
            System.out.println("Key: " + entry.getKey() + "\t Value: "
                    + entry.getValue());
        }

        System.out
                .println("** Keys and Values (Using java 8 using lambdas )***");
        map.forEach((k, v) -> System.out
                .println("Key: " + k + "\t value: " + v));
    }
}

Итерация карта очень проста.

for(Object key: map.keySet()){
   Object value= map.get(key);
   //Do your stuff
}

Например, у вас Map<String, int> data;

for(Object key: data.keySet()){
  int value= data.get(key);
}

Что ж, это излишне медленно, потому что сначала получите ключи, а затем записи. Альтернатива: получите набор записей, а затем для каждой записи установите ключ и значение

michaeak 12.12.2018 15:00

Есть много способов сделать это. Ниже приведены несколько простых шагов:

Предположим, у вас есть одна карта вроде:

Map<String, Integer> m = new HashMap<String, Integer>();

Затем вы можете сделать что-то вроде следующего, чтобы перебирать элементы карты.

// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
    Entry<String, Integer> pair = me.next();
    System.out.println(pair.getKey() + ":" + pair.getValue());
}

// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
    System.out.println(me.getKey() + " : " + me.getValue());
}

// *********** Using keySet *****************************
for(String s : m.keySet()){
    System.out.println(s + " : " + m.get(s));
}

// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
    String key = me.next();
    System.out.println(key + " : " + m.get(key));
}

Используйте Java 8:

map.entrySet().forEach(entry -> System.out.println(entry.getValue()));

Самый компактный с Java 8:

map.entrySet().forEach(System.out::println);

С помощью Java 8 вы можете перебирать Map, используя forEach и лямбда-выражение,

map.forEach((k, v) -> System.out.println((k + ":" + v)));

Эффективным итеративным решением для Map является цикл for от Java 5 до Java 7. Вот он:

for (String key : phnMap.keySet()) {
    System.out.println("Key: " + key + " Value: " + phnMap.get(key));
}

В Java 8 вы можете использовать лямбда-выражение для итерации по карте. Это улучшенный forEach

phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));

Если вы хотите написать условное выражение для лямбды, вы можете написать его так:

phnMap.forEach((k,v)->{
    System.out.println("Key: " + k + " Value: " + v);
    if ("abc".equals(k)){
        System.out.println("Hello abc");
    }
});

Мне нравится объединять счетчик, а затем сохранять окончательное значение счетчика;

int counter = 0;
HashMap<String, String> m = new HashMap<String, String>();
for(int i = 0;i<items.length;i++)
{
m.put("firstname"+i, items.get(i).getFirstName());
counter = i;
}

m.put("recordCount",String.valueOf(counter));

Затем, когда вы захотите получить:

int recordCount = Integer.parseInf(m.get("recordCount"));
for(int i =0 ;i<recordCount;i++)
{
System.out.println("First Name :" + m.get("firstname"+i));
}

Using Java 7

Map<String,String> sampleMap = new HashMap<>();
for (sampleMap.Entry<String,String> entry : sampleMap.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();

    /* your Code as per the Business Justification  */

}

Using Java 8

Map<String,String> sampleMap = new HashMap<>();

sampleMap.forEach((k, v) -> System.out.println("Key is :  " + k + " Value is :  " + v));

If I have an object implementing the Map interface in Java and I wish to iterate over every pair contained within it, what is the most efficient way of going through the map?

Если эффективность зацикливания ключей является приоритетом для вашего приложения, выберите реализацию Map, которая поддерживает ключи в желаемом порядке.

Will the ordering of elements depend on the specific map implementation that I have for the interface?

Да, конечно.

  • Некоторые реализации Map обещают определенный порядок итераций, другие - нет.
  • Различные реализации Map поддерживают разный порядок пар ключ-значение.

См. Эту таблицу, которую я создал, обобщая различные реализации Map в комплекте с Java 11. В частности, обратите внимание на столбец порядок итераций. Щелкните / коснитесь для увеличения.

Table of map implementations in Java 11, comparing their features

Вы можете видеть, что есть четыре реализации Map, поддерживающие порядок:

  • TreeMap
  • ConcurrentSkipListMap
  • LinkedHashMap
  • EnumMap

NavigableMap интерфейс

Два из них реализуют интерфейс NavigableMap: TreeMap и ConcurrentSkipListMap.

Старый интерфейс SortedMap фактически заменен новым интерфейсом NavigableMap. Но вы можете найти сторонние реализации, реализующие только старый интерфейс.

Естественный порядок

Если вам нужен Map, который хранит свои пары в «естественном порядке» ключа, используйте TreeMap или ConcurrentSkipListMap. Термин «естественный порядок» означает, что класс ключей реализует Comparable. Значение, возвращаемое методом compareTo, используется для сравнения при сортировке.

Изготовленный на заказ заказ

Если вы хотите указать настраиваемую процедуру сортировки для ваших ключей, которая будет использоваться при поддержании отсортированного порядка, передайте реализацию Comparator, соответствующую классу ваших ключей. Используйте TreeMap или ConcurrentSkipListMap, передав свой Comparator.

Исходный заказ на размещение

Если вы хотите, чтобы пары вашей карты оставались в том порядке, в котором вы их вставляли на карту, используйте LinkedHashMap.

Порядок определения перечисления

Если вы используете в качестве ключей перечисление, такое как DayOfWeek или Month, используйте класс EnumMap. Этот класс высоко не только оптимизирован для использования очень небольшого объема памяти и очень быстрой работы, но и поддерживает ваши пары в порядке, определенном перечислением. Например, для DayOfWeek ключ DayOfWeek.MONDAY будет найден первым при повторении, а ключ DayOfWeek.SUNDAY будет последним.

Прочие соображения

При выборе реализации Map также учитывайте:

  • NULL. Некоторые реализации запрещают / принимают NULL как ключ и / или значение.
  • Параллелизм. Если вы управляете картой между потоками, вы должны использовать реализацию, поддерживающую параллелизм. Или оберните карту Collections::synchronizedMap (менее предпочтительно).

Оба эти соображения отражены в графической таблице выше.

Поздний комментарий к ответу, который тоже опаздывает на вечеринку (но очень информативный). +1 от меня за упоминание EnumMap, так как я впервые слышу о нем. Вероятно, есть много случаев, когда это может пригодиться.

user991710 16.02.2020 21:42

Map.forEach

Как насчет простого использования Map::forEach, когда и ключ, и значение передаются в ваш BiConsumer?

map.forEach((k,v)->{
    System.out.println(k+"->"+v);
});

Это было описано в Ответ Ловы Читтумури. Также рассматривается как пункт 3 в Ответ Вячеслава Веденина, получившем большое количество голосов.

Basil Bourque 06.01.2020 10:51

Но доступно только на этикетке API 24.

Mahbubur Rahman Khan 06.03.2020 01:02

Начиная с Java 10, вы можете использовать вывод локальной переменной (также известный как «var»), чтобы сделать многие уже доступные ответы менее раздутыми. Например:

for (var entry : map.entrySet()) {
    System.out.println(entry.getKey() + " : " + entry.getValue());
}

Map<String, String> map = 
for (Map.Entry<String, String> entry : map.entrySet()) {
    MapKey = entry.getKey() 
    MapValue = entry.getValue();
}

Вы можете найти ключ и с его помощью найти связанное значение карты, так как карта имеет уникальный ключ, посмотрите, что происходит, когда ключ дублируется здесь или здесь.

Демо-карта:

 Map<String, String> map = new HashMap();
  map.put("name", "Badri Paudel");
  map.put("age", "23");
  map.put("address", "KTM");
  map.put("faculty", "BE");
  map.put("major", "CS");
  map.put("head", "AVD");
 

Чтобы получить только ключ, вы можете использовать map.keySet(); следующим образом:

for(String key : map.keySet()) {
      System.out.println(key);
  }

Чтобы получить только значение, вы можете использовать map.values(); следующим образом:

      for(String value : map.values()) {
      System.out.println(value);
  }

Чтобы получить и ключ, и его значение, вы все равно можете использовать map.keySet(); и получить соответствующее значение, например:

 //this prints the key value pair
  for (String k : map.keySet()) {
        System.out.println(k + " " + map.get(k) + " ");
    }

map.get(key) дает значение, указанное этим ключом.

Другие вопросы по теме