Soru HashMap üzerinden yineleme [duplicate]


Olası Kopyalama: 
Her bir girişte 'Harita' içinde verimli bir şekilde yineleme nasıl yapılır?

Öğeler üzerinde yineleme yapmanın en iyi yolu nedir? HashMap?


2833
2018-06-30 23:24


Menşei


Anahtarları ve değerleri almalı ve bunları çok boyutlu bir diziye eklemeliyim - burntsugar
Bunun bir kopyası olduğu sorudan daha yüksek bir skoru var mı? - immibis
Java 8'de Lambda Expression'u kullanarak: stackoverflow.com/a/25616206/1503859 - Nitin Mahesh
@immibis muhtemelen bir çok insan HashMaps'i diğer harita uygulamalarını dikkate almadan içgüdüsel olarak kullanması nedeniyle. Ardından, HashMap'ları üzerinde yinelemeye çalışırken, kaçınılmaz olarak sıkışıp kaldıklarında, Google’a “HashMap’tan geçiş yap” atarlar ve doğrudan buraya yönlendirirler. - Dean Wild


Cevaplar:


Üzerinden yineleyin entrySet() öyle:

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
    }
}

Hakkında daha fazla bilgi edinin Map.


2842
2018-06-30 23:27



Eski stil olsa da, bu aşağıdaki cevaplarda yeni foreach stili üzerinden ConcurrentModificationExceptions kaçınmanıza yardımcı olacaktır. Örneğin, ayrı yineleyici üzerinden çıkartabilirsiniz. - Benjamin Wootton
@ karim79 aşağıdaki yol hakkında ne düşünüyorsunuz: 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()); } - fresh_dev
'it.remove (); 'haritayı boşaltıyorsunuz, eğer bu harita bir sınıf değişkeni ise yeniden kullanılamaz. Bunun için bir çözüm var mı? - vimukthi
@vimukthi bunun için ne anlama geliyor? Sadece kaldır it.remove(); hat. - Danny
İçin (Map.Entry<String, Object> cursor : map.entrySet()) {...} sözdizimi çok daha iyi. - Chad Okere


Sadece anahtarlarla ilgileniyorsanız, keySet() haritanın

Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

Sadece değerlere ihtiyacınız varsa, kullanın values():

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

Son olarak, hem anahtar hem de değer istiyorsanız, entrySet():

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

Bir uyarı: Eğer iterasyonun ortalamasını kaldırmak isterseniz, bunu bir yineleyici ile yapmanız gerekir. karim79'un cevabı). Ancak, değişen öğe değerleri tamamdır (bkz. Map.Entry).


4130
2018-06-30 23:28



Peki eş zamanlı olarak 2 haritadan nasıl geçilir? entrySet yöntemini kullanarak? && kullanmaya çalıştım ama işim ddnt - DaMainBoss
İki yineleyici kullanın. Kabul edilen cevabı görmek için örneğin bir yineleyicinin kullanımı. - harto
Hem anahtarlara hem de değerlere ihtiyaç duyduğunuzda, entrySet'i kullanmak daha verimlidir. Sadece birine ya da diğerine ihtiyacınız varsa, sadece onu kullanın: stackoverflow.com/questions/3870064/... - rogerdpack
Daha önemli bir nokta, keySet () tarafından döndürülen Set ve () değerleri tarafından döndürülen Koleksiyonun her ikisi de orijinal Harita tarafından desteklenir. Yani, eğer herhangi bir değişiklik yaparsanız, bunlar Haritaya geri yansır, ancak ikisi de add () ve addAll () yöntemlerini desteklemez, yani Set'e veya yeni değere yeni anahtar ekleyemezsiniz. Koleksiyonda. - sactiw
Hem değerleri hem de anahtarları almayla ilgili olarak, yalnızca ilkini kullanmak daha kolay değildir. foreach örnek ve döngü içindeki değeri al, value = map.get(key)? Performansı mı entrySet daha yüksek? - Marco Sulla


Referanstan çıkarıldı Java'da bir harita üzerinde yineleme nasıl:

Bir üzerinde yineleme birkaç yolu vardır Map Java'da. En yaygın yöntemleri gözden geçirelim ve avantajlarını ve dezavantajlarını gözden geçirelim. Java'daki tüm haritalar Harita arayüzünü uyguladığı için, aşağıdaki teknikler herhangi bir harita uygulaması için çalışacaktır (HashMap, TreeMap, LinkedHashMap, Hashtable, vb.)

Yöntem 1: For-Each döngüsünü kullanarak girişleri yinelemek.

Bu en yaygın yöntemdir ve çoğu durumda tercih edilir. Döngüde her iki harita anahtarına ve değerlere ihtiyacınız varsa kullanılmalıdır.

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 döngüsünün Java 5'te tanıtıldığını unutmayın, bu nedenle bu yöntem yalnızca dilin daha yeni sürümlerinde çalışır. Ayrıca For-Her bir döngü atmak NullPointerException null olan bir harita üzerinde yinelemeyi denerseniz, yinelenmeden önce null referanslarını kontrol etmelisiniz.

2. Yöntem: For-Each döngüsünü kullanarak anahtarların veya değerlerin üzerinde yineleme.

Haritadan yalnızca anahtarlara veya değerlere ihtiyacınız varsa, inputSet yerine keySet veya değerler üzerinde yineleyebilirsiniz.

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

Bu yöntem, üzerinde küçük bir performans avantajı sağlar entrySet Yineleme (yaklaşık% 10 daha hızlı) ve daha temiz.

Yöntem 3: Yineleyici kullanarak yineleme.

Jenerik Kullanımı:

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

Jenerik Olmadan:

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

Aynı tekniği tekrarlamak için de kullanabilirsiniz keySet veya değerler.

Bu yöntem gereksiz görünebilir, ancak kendi avantajları vardır. Her şeyden önce, Java'nın eski sürümlerinde bir harita üzerinde yinelemenin tek yolu budur. Diğer önemli özellik, yinelenen arama sırasında haritayı girişleri silmenizi sağlayan tek yöntem olmasıdır. iterator.remove(). Her bir yineleme sırasında bunu yapmaya çalışırsanız, "öngörülemeyen sonuçlar" elde edersiniz. Javadoc.

Performans bakış açısından, bu yöntem bir Her Bir yinelemeye eşittir.

Yöntem 4: Tuşların üzerinde geçiş yapmak ve değerleri aramak (verimsiz).

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

Bu yöntem # 1 için daha temiz bir alternatif gibi görünebilir, ancak pratikte bir anahtar tarafından değerlerin alınması zaman alıcı olabileceği için oldukça yavaş ve verimsizdir (farklı Harita uygulamalarındaki bu yöntem yöntem # 1'den% 20 -% 200 daha yavaştır) ). FindBugs kuruluysa, bunu algılar ve verimsiz yineleme hakkında sizi uyarır. Bu yöntemden kaçınılmalıdır.

Sonuç:

Haritadan yalnızca anahtarlara veya değerlere ihtiyacınız varsa, # 2 yöntemini kullanın. Java'nın eski sürümüyle (5'ten az) sıkışmış veya yineleme sırasında girdileri kaldırmayı planlıyorsanız, # 3 yöntemini kullanmanız gerekir. Aksi takdirde # 1 yöntemini kullanın.


740
2017-12-08 14:19



Küçük caeveti ekleyelim. ConcurrentMaps, yineleme keySet() genel olarak çökecektir (daha önce toplanan anahtarlar için değerlerin bulunmadığının garantisi yoktur). Diğer yandan yineleyicileri veya girdileri kullanmak güvenlidir (her zaman mevcut nesnelere başvururlar). - P Marecki
@Arvind 4. yöntem hiç verimli olmaz mıydı? Tanımı gereği get() HashMap için her zaman O (1) 'dir. HashMap'in tanımı budur ve kullanıcı bir HashMap istemiştir. Bunun neden bu kadar yüksek olduğunu anlamıyorum. Başka birinin bağlantısını referans gösterecekseniz, sorulan soru için gerçekten mantıklı olduğundan emin olun. - ohbrobig


Bir girişteki girişleri yineleyebilirsiniz. Map çeşitli yollarla. Her anahtarı ve değeri şu şekilde alın:

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

Ya da anahtarların listesini alabilirsiniz.

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

Sadece tüm değerleri almak ve anahtarlar ile ilgilenmiyorsanız, şunları kullanabilirsiniz:

Collection<?> values = map.values();

77
2018-06-30 23:43





for (Map.Entry<String, String> item : params.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}

70
2017-07-23 01:28





Daha akıllı:

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

55
2017-08-11 10:01



Bu aslında anahtarlara ihtiyacınız olup olmadığına bağlıdır. değilse, hashCode () çağrılmadığı için entrySet () öğesini kullanmak daha verimlidir. - icfantv
Her yineleme için map.get (anahtar) daha akıllı değil - daha yavaş - ComputerEngineer88
Hem anahtar hem de değer içeren girdileri döndüren map.entrySet (). Bu şekilde, hashCode () öğesini çağırmanız ve yineleme sırasında hashta arama yapmanız gerekmez. - ComputerEngineer88
Java 8 sözdizimi. Android geliştirme için hala çalışmayabilir. "Android, herhangi bir Java SE API sürümü ile% 100 uyumlu değildir, 6 ya da 8 değil, herhangi bir ... JRE, Java Runtime Environment iken, JDK, Java Geliştirme Seti'dir. İhtiyacınız olan JDK'sıdır. Mevcut Android SDK.Dec 9, 2013 ile birlikte Android uygulama geliştirme için " kaynak - jasonleonhard


Bağlı. Her bir girdinin anahtarına ve değerine ihtiyacınız olacağını biliyorsanız, o zaman entrySet. Sadece değerlere ihtiyacınız varsa, o zaman values() yöntem. Ve sadece tuşlara ihtiyacınız varsa, o zaman kullanın keyset().

Kötü bir uygulama, tüm anahtarlar boyunca yinelemek ve ardından döngü içinde her zaman map.get(key) değeri almak için. Bunu yapıyorsan, yazdığım ilk seçenek senin için.


40
2018-06-30 23:29



Daha önemli bir nokta, keySet () tarafından döndürülen Set ve () değerleri tarafından döndürülen Koleksiyonun her ikisi de orijinal Harita tarafından desteklenir. Yani, eğer herhangi bir değişiklik yaparsanız, bunlar Haritaya geri yansır, ancak ikisi de add () ve addAll () yöntemlerini desteklemez, yani Set'e veya yeni değere yeni anahtar ekleyemezsiniz. Koleksiyonda. - sactiw