두지도 병합 Java 8 Stream API 사용
두 개 이상의 Map<String, Integer>개체가 있습니다. 공통 키 값이 최대 값이어야하는 방식으로 Java 8 Stream API와 병합하고 싶습니다.
@Test
public void test14() throws Exception {
Map<String, Integer> m1 = ImmutableMap.of("a", 2, "b", 3);
Map<String, Integer> m2 = ImmutableMap.of("a", 3, "c", 4);
List<Map<String, Integer>> list = newArrayList(m1, m2);
Map<String, Integer> mx = list.stream()... // TODO
Map<String, Integer> expected = ImmutableMap.of("a", 3, "b", 3, "c", 4);
assertEquals(expected, mx);
}
이 테스트 방법을 녹색으로 만들 수있는 방법은 무엇입니까?
내가 연주 한 collect과 Collectors어떤 성공없이 잠시 동안.
( ImmutableMap그리고 newArrayList구글 구아바에서 있습니다.)
@Test
public void test14() throws Exception {
Map<String, Integer> m1 = ImmutableMap.of("a", 2, "b", 3);
Map<String, Integer> m2 = ImmutableMap.of("a", 3, "c", 4);
Map<String, Integer> mx = Stream.of(m1, m2)
.map(Map::entrySet) // converts each map into an entry set
.flatMap(Collection::stream) // converts each set into an entry stream, then
// "concatenates" it in place of the original set
.collect(
Collectors.toMap( // collects into a map
Map.Entry::getKey, // where each entry is based
Map.Entry::getValue, // on the entries in the stream
Integer::max // such that if a value already exist for
// a given key, the max of the old
// and new value is taken
)
)
;
/* Use the following if you want to create the map with parallel streams
Map<String, Integer> mx = Stream.of(m1, m2)
.parallel()
.map(Map::entrySet) // converts each map into an entry set
.flatMap(Collection::stream) // converts each set into an entry stream, then
// "concatenates" it in place of the original set
.collect(
Collectors.toConcurrentMap( // collects into a map
Map.Entry::getKey, // where each entry is based
Map.Entry::getValue, // on the entries in the stream
Integer::max // such that if a value already exist for
// a given key, the max of the old
// and new value is taken
)
)
;
*/
Map<String, Integer> expected = ImmutableMap.of("a", 3, "b", 3, "c", 4);
assertEquals(expected, mx);
}
Map<String, Integer> mx = new HashMap<>(m1);
m2.forEach((k, v) -> mx.merge(k, v, Integer::max));
mx = list.stream().collect(HashMap::new,
(a, b) -> b.forEach((k, v) -> a.merge(k, v, Integer::max)),
Map::putAll);
이것은 모든 크기 목록에 대한 일반적인 경우를 다루며 모든 유형에서 작동해야 하며 원하는대로 Integer::max및 / 또는 교체하기 만하면 HashMap::new됩니다.
병합에서 어떤 값이 나오는지 신경 쓰지 않는다면 훨씬 더 깔끔한 솔루션이 있습니다.
mx = list.stream().collect(HashMap::new, Map::putAll, Map::putAll);
그리고 일반적인 방법으로 :
public static <K, V> Map<K, V> mergeMaps(Stream<? extends Map<K, V>> stream) {
return stream.collect(HashMap::new, Map::putAll, Map::putAll);
}
public static <K, V, M extends Map<K, V>> M mergeMaps(Stream<? extends Map<K, V>> stream,
BinaryOperator<V> mergeFunction, Supplier<M> mapSupplier) {
return stream.collect(mapSupplier,
(a, b) -> b.forEach((k, v) -> a.merge(k, v, mergeFunction)),
Map::putAll);
}
관심이있는 모든 사람을 위해 @srborlongan이 한 작업을 시각적으로 표현했습니다.
I added my contribution to the proton pack library which contains utility methods for the Stream API. Here's how you could achieve what you want:
Map<String, Integer> mx = MapStream.ofMaps(m1, m2).mergeKeys(Integer::max).collect();
Basically mergeKeys will collect the key-value pairs in a new map (providing a merge function is optional, you'll end up with a Map<String, List<Integer>> otherwise) and recall stream() on the entrySet() to get a new MapStream. Then use collect() to get the resulting map.
Using StreamEx you can do:
StreamEx.of(m1, m2)
.flatMapToEntry(x -> x)
.grouping(IntCollector.max())
참고URL : https://stackoverflow.com/questions/23038673/merging-two-mapstring-integer-with-java-8-stream-api
'program story' 카테고리의 다른 글
| iOS UILabel에 왼쪽 패딩 추가 (0) | 2020.11.19 |
|---|---|
| 둘 이상의 EditText에 대한 TextWatcher (0) | 2020.11.19 |
| NLTK 데이터 다운로드 중 SSL 오류 (0) | 2020.11.19 |
| HTML5 iFrame Seamless 속성 (0) | 2020.11.19 |
| 프로토 타입 VS jQuery-강점과 약점? (0) | 2020.11.19 |
