dictionary 배열 list - Java Map의 각 항목을 효율적으로 반복하는 방법은 무엇입니까?




15 Answers

다른 답변을 요약하고 내가 아는 것과 결합하기 위해이 작업을 수행하는 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. foreachMap.Entry 사용

    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
    
  3. Java 8에서 forEach 사용하기

    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
    
  4. keySetforeach 사용

    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
    
  5. 키 세트 및 반복기 사용

    long i = 0;
    Iterator<Integer> itr2 = map.keySet().iterator();
    while (itr2.hasNext()) {
        Integer key = itr2.next();
        i += key + map.get(key);
    }
    
  6. forMap.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. Apache Collections IterableMap 사용하기

    long i = 0;
    MapIterator<Integer, Integer> it = iterableMap.mapIterator();
    while (it.hasNext()) {
        i += it.next() + it.getValue();
    }
    
  10. Eclipse (CS) 컬렉션의 MutableMap 사용

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

성능 테스트 (모드 = AverageTime, 시스템 = Windows 8.1 64 비트, Intel i7-4790 3.60 GHz, 16 GB)

  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
    

그래프 (지도 크기에 따른 성능 테스트)

표 (지도 크기에 따른 성능 테스트)

          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

모든 테스트는 GitHubGitHub .

string object >>

Java에서 Map 인터페이스를 구현하는 객체가 있고 그 안에 포함 된 모든 쌍을 반복하고 싶다면지도를 통과하는 가장 효율적인 방법은 무엇입니까?

요소의 순서는 인터페이스에 대한 특정 맵 구현에 따라 결정됩니까?




예, 순서는 특정 Map 구현에 따라 다릅니다.

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



반복자 및 제네릭 사용 예제 :

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



지도를 반복 할 수있는 몇 가지 방법이 있습니다.

지도에 백만 개의 키 값 쌍을 저장하여지도에 저장된 공통 데이터 세트에 대한 실적을 비교 한 다음지도를 반복합니다.

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 사용하기

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 사용하기

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

75 밀리 초

나는 this link .




이를 수행하는 올바른 방법은 허용 된 답변을 가장 효율적으로 사용하는 것입니다. 다음 코드는 조금 더 깨끗해 보입니다.

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



자바 1.4에서 이것을 사용해보십시오 :

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

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

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

  //...
}



Java 8 :

람다 식을 사용할 수 있습니다.

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

자세한 내용은 다음을 참조 this .




지도에서 keys 및 / 또는 values 및 / 또는 both (eg, entrySet) 대한 반복 both (eg, entrySet) 은 관심있는 in_에 따라 달라질 수 있습니다. 좋아요 :

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()both -> entrySet() 반복합니다.

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

게다가, HashMap을 통해 반복하는 3 가지 다른 방법이 있습니다. 그들은 다음과 같습니다 _

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

또는

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



Java 8에서 가장 컴팩트 한 :

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



제네릭을 사용하여 할 수 있습니다.

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

            }



예, 많은 사람들이 이것이 Map 를 반복하는 가장 좋은 방법이라고 동의했기 때문입니다.

그러나 맵이 null 경우 nullpointerexception 을 던질 가능성이 있습니다. null .check를 넣는 것을 잊지 마십시오.

                                                 |
                                                 |
                                         - - - -
                                       |
                                       |
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = 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은 맵에 의해 뒷받침됩니다. 두 번째 방법은 람다 (lambda)를 사용할 수 있기 때문에 편리합니다. 예를 들어 5보다 큰 Integer 객체 만 인쇄하려는 경우에 유용합니다.

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, # 9, # 9, # 8, # 8, # 7, # 7 : 7,6 (# 6) : 6, 5 1, 0 (# = 1) : 0, # 1, # 2, # 3,

LinkedHashMap (2) :

10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1,

HashMap (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) :

1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7,8 : 8,9 : 9,10 :




Related