Map
Java로 인터페이스를 구현하는 객체가 있고 그 안에 포함 된 모든 쌍을 반복하려면 맵을 통과하는 가장 효율적인 방법은 무엇입니까?
요소의 순서는 인터페이스에 대한 특정 맵 구현에 따라 달라 집니까?
답변
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
답변
다른 답변을 요약하고 내가 아는 것과 결합하기 위해 10 가지 주요 방법을 찾았습니다 (아래 참조). 또한 성능 테스트를 작성했습니다 (아래 결과 참조). 예를 들어,지도의 모든 키와 값의 합계를 찾으려면 다음과 같이 쓸 수 있습니다.
-
사용 반복자 와 의 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(); }
-
사용 의 foreach 와 의 Map.Entry를
long i = 0; for (Map.Entry<Integer, Integer> pair : map.entrySet()) { i += pair.getKey() + pair.getValue(); }
-
Java 8에서 forEach 사용
final long[] i = {0}; map.forEach((k, v) -> i[0] += k + v);
-
사용 keySet 반환 및 foreach 문을
long i = 0; for (Integer key : map.keySet()) { i += key + map.get(key); }
-
사용 keySet 반환 및 반복자를
long i = 0; Iterator<Integer> itr2 = map.keySet().iterator(); while (itr2.hasNext()) { Integer key = itr2.next(); i += key + map.get(key); }
-
사용 을 위해 와 의 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(); }
-
Java 8 스트림 API 사용
final long[] i = {0}; map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
-
Java 8 Stream API 병렬 사용
final long[] i = {0}; map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
-
사용 IterableMap 의를
Apache Collections
long i = 0; MapIterator<Integer, Integer> it = iterableMap.mapIterator(); while (it.hasNext()) { i += it.next() + it.getValue(); }
-
이클립스 (CS) 컬렉션의 MutableMap 사용
final long[] i = {0}; mutableMap.forEachKeyValue((key, value) -> { i[0] += key + value; });
성능 테스트 (모드 = AverageTime, 시스템 = Windows 8.1 64 비트, Intel i7-4790 3.60GHz, 16GB)
-
작은지도 (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
-
요소가 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
-
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
모든 테스트는 GitHub에서 이루어 집니다.
답변
Java 8에서는 새로운 람다 기능을 사용하여 깨끗하고 빠르게 할 수 있습니다.
Map<String,String> map = new HashMap<>();
map.put("SomeKey", "SomeValue");
map.forEach( (k,v) -> [do something with key and value] );
// such as
map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));
의 유형 k
및 v
컴파일러에 의해 추정되며 사용할 필요가 없다 Map.Entry
더 이상은.
쉬워요!
답변
예, 순서는 특정지도 구현에 따라 다릅니다.
@ 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();
// ...
}
답변
지도를 반복하는 일반적인 코드는 다음과 같습니다.
Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
String key = entry.getKey();
Thing thing = entry.getValue();
...
}
HashMap
표준 맵 구현이며 보장하지 않습니다 (또는 돌연변이 작업이 수행되지 않으면 순서를 변경해서는 안됩니다). SortedMap
키의 자연 순서에 따라 항목을 반환하거나 Comparator
제공된 경우을 반환합니다 . LinkedHashMap
구성 방식에 따라 게재 신청서 또는 액세스 순서로 항목을 반환합니다. EnumMap
자연 순서대로 키를 반환합니다.
(업데이트 :. 나는 이것이 더 이상 진실이라고 생각하지 않습니다 ) 참고 IdentityHashMap
entrySet
반복자는 현재 같은 반환하는 특유의 구현이 Map.Entry
의 모든 항목에 대한 인스턴스를 entrySet
! 그러나 새로운 반복자가 진행할 때마다 Map.Entry
가 업데이트됩니다.
답변
반복자와 제네릭을 사용하는 예 :
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();
// ...
}
답변
이것은 두 가지 질문입니다.
@ ScArcher2 맵의 항목을 반복하는 방법 은 완벽하게 답변 했습니다.
반복 순서는 무엇인가 -만약 당신이 단지 사용 Map
하고 엄격히 말하면, 순서 보장 은 없다 . 따라서 구현에서 제공 한 순서에 의존해서는 안됩니다. 그러나 SortedMap
인터페이스가 확장 Map
되어 원하는 것을 정확하게 제공합니다. 구현은 일관된 정렬 순서를 제공합니다.
NavigableMap
또 다른 유용한 확장입니다 -이것은 SortedMap
키 세트에서 순서대로 위치를 찾는 추가 방법입니다. 그래서 가능성이 처음부터 반복의 필요성을 제거 할 수 있습니다 – 당신은 특정 찾을 수 있습니다 entry
당신이 사용 후입니다 higherEntry
, lowerEntry
, ceilingEntry
, 또는 floorEntry
방법. 이 descendingMap
방법 은 순회 순서 를 취소 하는 명시적인 방법도 제공합니다 .