dictionary map foreach - Comment effectuer une itération efficace sur chaque entrée d'une carte Java?





15 Answers

Pour résumer les autres réponses et les combiner avec ce que je sais, j'ai trouvé 10 façons principales de le faire (voir ci-dessous). J'ai également écrit des tests de performance (voir les résultats ci-dessous). Par exemple, si nous voulons trouver la somme de toutes les clés et de toutes les valeurs d'une carte, nous pouvons écrire:

  1. Utiliser itérateur et 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. Utiliser foreach et Map.Entry

    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
    
  3. Utilisation de forEach à partir de Java 8

    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
    
  4. Utiliser keySet et foreach

    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
    
  5. Utilisation de keySet et d' itérateur

    long i = 0;
    Iterator<Integer> itr2 = map.keySet().iterator();
    while (itr2.hasNext()) {
        Integer key = itr2.next();
        i += key + map.get(key);
    }
    
  6. Utiliser pour et 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. Utilisation de l' API Java 8 Stream

    final long[] i = {0};
    map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  8. Utilisation parallèle de l'API Java 8 Stream

    final long[] i = {0};
    map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  9. Utilisation de Apache Collections IterableMap of Apache Collections

    long i = 0;
    MapIterator<Integer, Integer> it = iterableMap.mapIterator();
    while (it.hasNext()) {
        i += it.next() + it.getValue();
    }
    
  10. Utilisation de collections MutableMap of Eclipse (CS)

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

Tests de performances (mode = AverageTime, système = Windows 8.1 64 bits, Intel i7-4790 3.60 GHz, 16 Go)

  1. Pour une petite carte (100 éléments), le score 0,308 est le meilleur

    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. Pour une carte avec 10000 éléments, le score 37.606 est le meilleur

    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. Pour une carte avec 100 000 éléments, le score 1184.767 est le meilleur

    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
    

Graphes (tests de performance en fonction de la taille de la carte)

Tableau (tests de performance en fonction de la taille de la carte)

          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

Tous les tests sont sur GitHub .

parcourir hashmap iterate

Si j’ai un objet implémentant l’interface Map en Java et que je souhaite parcourir toutes les paires qu’il contient, quel est le moyen le plus efficace de parcourir la carte?

La commande des éléments dépendra-t-elle de la mise en oeuvre de carte spécifique que j'ai pour l'interface?




Oui, l'ordre dépend de l'implémentation spécifique de la carte.

@ ScArcher2 a la syntaxe Java 1.5 plus élégante . En 1.4, je ferais quelque chose comme ceci:

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



Exemple d'utilisation d'itérateur et de génériques:

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



Il y a plusieurs façons de parcourir la carte.

Voici une comparaison de leurs performances pour un ensemble de données commun stocké dans la carte en stockant un million de paires de valeurs de clé dans la carte.

1) Utiliser entrySet() pour chaque boucle

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

50 millisecondes

2) Utiliser keySet() pour chaque boucle

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

76 millisecondes

3) Utiliser entrySet() et l'itérateur

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

50 millisecondes

4) Utiliser keySet() et itérateur

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

75 millisecondes

J'ai référé this link .




Pour ce faire, utilisez la réponse acceptée, car elle est la plus efficace. Je trouve le code suivant un peu plus propre.

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



Essayez ceci avec Java 1.4:

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

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

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

  //...
}



Java 8:

Vous pouvez utiliser des expressions lambda:

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

Pour plus d'informations, suivez this .




Dans Map, on peut modifier les keys et / ou les values et / ou les both (eg, entrySet) fonction de l’intérêt de _ Like:

1.) Parcourez les keys -> keySet() de la carte:

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

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

2.) Parcourez les values -> values() de la carte:

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

3.) Parcourez les both -> entrySet() de la carte:

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

De plus, il existe 3 manières différentes de parcourir un HashMap. Ils sont comme ci-dessous _

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



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

OU

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



Le plus compact avec Java 8:

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



Vous pouvez le faire en utilisant des génériques:

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



Utilisez Java 8:

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



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

            }



Oui, comme beaucoup de gens l’ont convenu, c’est le meilleur moyen de parcourir une Map .

Mais il y a des chances de nullpointerexception si la carte est null . N'oubliez pas de mettre null .check in.

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



Le classement dépendra toujours de l’implémentation spécifique de la carte. En utilisant Java 8, vous pouvez utiliser l’un des deux suivants:

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

Ou:

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

Le résultat sera le même (même ordre). EntrySet soutenu par la carte afin que vous obteniez le même ordre. Le second est pratique car il vous permet d’utiliser lambdas, par exemple si vous souhaitez uniquement imprimer uniquement les objets Integer supérieurs à 5:

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

Le code ci-dessous montre l'itération via LinkedHashMap et HashMap normal (exemple). Vous verrez la différence dans la commande:

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,




Related