Итерация через HashMap

Возможный дубликат:
Как эффективно перебирать каждую запись на «карте»?

Каков наилучший способ перебора элементов в HashMap ?

вопрос задан 30.06.2009
burntsugar
22755 репутация

7 ответов


  • 4183 рейтинг

    Если вас интересуют только ключи, вы можете выполнить итерацию через keySet() карты:

     Map<String, Object> map = ...;
    
    for (String key : map.keySet()) {
        // ...
    }
     

    Если вам нужны только значения, используйте values() :

     for (Object value : map.values()) {
        // ...
    }
     

    Наконец, если вы хотите как ключ, так и значение, используйте entrySet() :

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

    Одно предупреждение: если вы хотите удалить элементы в середине итерации, вам нужно сделать это через Iterator (см . Ответ karim79 ). Однако изменение значений элементов в порядке (см. Map.Entry ).

    ответ дан harto, с репутацией 70539, 30.06.2009
  • 2875 рейтинг

    Итерацию через entrySet() так:

     public static void printMap(Map mp) {
        Iterator it = mp.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            System.out.println(pair.getKey() + " = " + pair.getValue());
            it.remove(); // avoids a ConcurrentModificationException
        }
    }
     

    Подробнее о Map .

    ответ дан karim79, с репутацией 289168, 30.06.2009
  • 748 рейтинг

    Извлечение из ссылки Как перебирать карту в Java :

    Существует несколько способов итерации над Map в Java. Давайте рассмотрим наиболее распространенные методы и рассмотрим их преимущества и недостатки. Поскольку все карты в Java реализуют интерфейс Map, для любой реализации карты ( HashMap , TreeMap , LinkedHashMap , Hashtable и т. Д.) Будут работать следующие методы:

    Метод №1 : Итерирование записей с использованием цикла For-Each.

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

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

    Обратите внимание, что цикл For-Every был введен в Java 5, поэтому этот метод работает только в более новых версиях языка. Также цикл For-Each будет генерировать NullPointerException если вы попытаетесь выполнить итерацию по карте, которая равна null, поэтому перед итерацией вы всегда должны проверять наличие нулевых ссылок.

    Метод №2 : Итерирование по клавишам или значениям с использованием цикла For-Each.

    Если вам нужны только ключи или значения на карте, вы можете выполнять итерацию по keySet или значениям вместо entrySet.

     Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    
    // Iterating over keys only
    for (Integer key : map.keySet()) {
        System.out.println("Key = " + key);
    }
    
    // Iterating over values only
    for (Integer value : map.values()) {
        System.out.println("Value = " + value);
    }
     

    Этот метод дает небольшое преимущество перед entrySet итерациями (примерно на 10% быстрее) и более чистым.

    Метод № 3 : Итерация с использованием Итератора.

    Использование дженериков:

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

    Без дженериков:

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

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

    Этот метод может выглядеть излишним, но он имеет свои преимущества. Прежде всего, это единственный способ перебора карты в более старых версиях Java. Другая важная особенность заключается в том, что это единственный метод, который позволяет удалять записи с карты во время итерации, вызывая iterator.remove() . Если вы попытаетесь сделать это во время каждой итерации, вы получите «непредсказуемые результаты» в соответствии с Javadoc .

    С точки зрения производительности этот метод равен Итерации For-Each.

    Метод №4 : Итерация по клавишам и поиск значений (неэффективные).

     Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    for (Integer key : map.keySet()) {
        Integer value = map.get(key);
        System.out.println("Key = " + key + ", Value = " + value);
    }
     

    Это может выглядеть как более чистая альтернатива для метода №1, но на практике это довольно медленно и неэффективно, так как получение значений с помощью ключа может занять много времени (этот метод в разных реализациях Map на 20% -200% медленнее, чем метод # 1 ). Если у вас установлен FindBugs, он обнаружит это и предупредит вас о неэффективной итерации. Этот метод следует избегать.

    Вывод:

    Если вам нужны только ключи или значения с карты, используйте метод # 2. Если вы застряли со старой версией Java (менее 5) или планируете удалять записи во время итерации, вы должны использовать метод # 3. В противном случае используйте метод # 1.

    ответ дан arvind, с репутацией 7515, 8.12.2011
  • 79 рейтинг
    for (Map.Entry<String, String> item : params.entrySet()) {
        String key = item.getKey();
        String value = item.getValue();
    }
    
    ответ дан gabor, с репутацией 1938, 23.07.2011
  • 79 рейтинг

    Вы можете перебирать записи в Map несколькими способами. Получите каждый ключ и оцените следующее:

     Map<?,?> map = new HashMap<Object, Object>();
    for(Entry<?, ?> e: map.entrySet()){
        System.out.println("Key " + e.getKey());
        System.out.println("Value " + e.getValue());
    }
     

    Или вы можете получить список ключей с помощью

     Collection<?> keys = map.keySet();
    for(Object key: keys){
        System.out.println("Key " + key);
        System.out.println("Value " + map.get(key));
    }
     

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

     Collection<?> values = map.values();
     
    ответ дан codethulhu, с репутацией 3172, 30.06.2009
  • 56 рейтинг

    Smarter:

     for (String key : hashMap.keySet()) {
        System.out.println("Key: " + key + ", Value: " + map.get(key));
    }
     
    ответ дан jkarretero, с репутацией 747, 11.08.2010
  • 41 рейтинг

    Зависит. Если вы знаете, что вам понадобятся как ключ, так и значение каждой записи, перейдите к entrySet . Если вам просто нужны значения, то есть values() метод. И если вам просто нужны ключи, используйте keyset() .

    Плохая практика заключается в том, чтобы перебирать все ключи, а затем в цикле всегда делать map.get(key) чтобы получить значение. Если вы это делаете, то первый вариант, который я написал, для вас.

    ответ дан Gary Kephart, с репутацией 3190, 30.06.2009