Вопрос по java, hashmap – Итерация по HashMap [дубликат]

3059

Possible Duplicate:
How to efficiently iterate over each entry in a 'Map'?

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

В Java 8 используется лямбда-выражение:stackoverflow.com/a/25616206/1503859 Nitin Mahesh
Как это имеет более высокий балл, чем вопрос, дубликат которого он имеет? immibis
@immibis, вероятно, потому что многие люди инстинктивно используют HashMaps, не обращая внимания на другие реализации карт. Затем, когда они неизбежно застревают, пытаясь перебрать свой HashMap, они пробивают «Перебрать через HashMap». в Google, ведя их прямо здесь. Dean Wild
Проверить ответ :stackoverflow.com/a/53497541/5756557 Anand
Мне нужно получить ключи и значения и добавить их в многомерный массив burntsugar

Ваш Ответ

7   ответов
115
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}
Является ли param именем HashMap?
@ChanjungKim да, это имя HashMap
4383

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

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

Итак, как сделать цикл через 2 карты одновременно? используя метод entrySet? Я пытался использовать & amp; но это не работает
Используйте два итератора. Смотрите принятый ответ, например, использование итератора.
Что касается получения значений и ключей, то не просто использовать первыйforeach пример и получить значение внутри цикла, сvalue = map.get(key)? Является ли производительностьentrySet более высокий?
Более эффективно использовать entrySet только тогда, когда вам нужны и ключи, и значения. Если вам нужен только один или другой, просто используйте этот:stackoverflow.com/questions/3870064/…
Еще один важный момент: Set, возвращаемый keySet (), и Collection, возвращаемый values (), поддерживаются исходной картой. То есть, если вы внесете в них какие-либо изменения, они будут отражены обратно на карте, однако оба они не поддерживают методы add () и addAll (), т. Е. Вы не можете добавить новый ключ в Set или новое значение. в коллекции.
43

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

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

Еще один важный момент: Set, возвращаемый keySet (), и Collection, возвращаемый values (), поддерживаются исходной картой. То есть, если вы внесете в них какие-либо изменения, они будут отражены обратно на карте, однако оба они не поддерживают методы add () и addAll (), т. Е. Вы не можете добавить новый ключ в Set или новое значение. в коллекции.
85

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

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.

Для(Map.Entry<String, Object> cursor : map.entrySet()) {...} синтаксис намного лучше.
@ karim79 что вы думаете о следующем пути: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()); }
@vimukthi, что вы имеете в виду решение этого? Просто удалитеit.remove(); линия.
вызывая it.remove (); & APOS; Вы очищаете карту, делая ее не пригодной для повторного использования, если эта карта была переменной класса. У вас есть какое-то решение?
Несмотря на старый стиль, это поможет избежать исключений ConcurrentModificationException по сравнению с новым стилем foreach в ответах ниже. Например, вы можете удалить через отдельный итератор.
787

Как перебрать карту в Java:

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

Method #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-Each был введен в Java 5, поэтому этот метод работает только в более новых версиях языка. Также цикл For-Each будет выбрасыватьNullPointerException Если вы пытаетесь перебрать карту, которая является нулевой, то перед итерацией вы всегда должны проверять наличие нулевых ссылок.

Method #2: Перебирая ключи или значения, используя цикл For-Each.

Если вам нужны только ключи или значения из карты, вы можете перебирать набор ключей или значения вместо 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% быстрее) и более чистая.

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

Используя Generics:

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.

С точки зрения производительности этот метод равен итерации для каждого.

Method #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, он обнаружит это и предупредит вас о неэффективной итерации. Этого метода следует избегать.

Conclusion:

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

Добавим маленькую пещеру, которая в случаеConcurrentMapс, итерация наkeySet() в целом произойдет сбой (нет гарантии, что значения существуют для ранее собранных ключей). С другой стороны, использование итераторов или записей безопасно (они всегда ссылаются на существующие объекты).
@arvind Как метод № 4 может быть неэффективным? По определениюget() всегда O (1) для HashMap. Это определение HashMap, и пользователь запросил HashMap. Я не понимаю, почему это так высоко проголосовало. Если вы собираетесь ссылаться на чужую ссылку, убедитесь, что она действительно имеет смысл для задаваемого вопроса.
60

for (String key : hashMap.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
это на самом деле зависит от того, нужны ли вам ключи. если нет, то более эффективно использовать entrySet (), поскольку hashCode () не вызывается.
map.get (ключ) для каждой итерации не умнее - его путь медленнее
map.entrySet (), которая возвращает записи, которые уже содержат ключ и значение. Таким образом, вам не нужно вызывать hashCode () и искать хеш во время итерации.
Синтаксис Java 8. Может все еще не работать для разработки Android. & quot; Android не на 100% совместим ни с какой версией Java SE API, ни с 6, ни с 8, ни с какой-либо другой версией. ... JRE - это среда выполнения Java, а JDK - это комплект разработки Java. Это JDK, который вам нужен для разработки приложений Android вместе с существующим Android SDK. Dec 9, 2013 & quot;source

Похожие вопросы