Java8: Stream / Map-Reduce / Collector를 사용 한 HashMap to HashMap
심플한 Java를 '변혁'하는 방법을 알고 있다List
부터Y
->Z
(예:
List<String> x;
List<Integer> y = x.stream()
.map(s -> Integer.parseInt(s))
.collect(Collectors.toList());
이제 지도에서도 기본적으로 동일한 작업을 수행하려고 합니다.
INPUT:
{
"key1" -> "41", // "41" and "42"
"key2" -> "42" // are Strings
}
OUTPUT:
{
"key1" -> 41, // 41 and 42
"key2" -> 42 // are Integers
}
솔루션은 다음과 같이 제한해서는 안 됩니다.String
->Integer
. 마치...List
위의 예에서는 임의의 메서드(또는 컨스트럭터)를 호출하고 싶습니다.
Map<String, String> x;
Map<String, Integer> y =
x.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey(),
e -> Integer.parseInt(e.getValue())
));
리스트 코드만큼 좋진 않아요새로 구성할 수 없습니다.Map.Entry
s in a에 있습니다.map()
작업이 에 섞이도록 호출하다collect()
불러.
여기 Sotirios Delimanolis의 답변이 몇 가지 변형되어 있습니다. (+1)로 시작하는 것이 좋습니다.다음 사항을 고려하십시오.
static <X, Y, Z> Map<X, Z> transform(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
return input.keySet().stream()
.collect(Collectors.toMap(Function.identity(),
key -> function.apply(input.get(key))));
}
여기에 몇 가지 포인트가 있습니다.첫 번째는 범용에서 와일드카드를 사용하는 것입니다.이것에 의해, 기능이 어느 정도 유연해집니다.예를 들어 출력 맵에 입력 맵 키의 슈퍼 클래스인 키를 사용하는 경우 와일드카드가 필요합니다.
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(지도의 값에 대한 예도 있지만, 실제로 조작된 것이며 Y에 대한 경계 와일드카드가 있는 것은 엣지의 경우에만 도움이 된다는 것을 인정합니다.
두 번째 포인트는 입력 맵에서 스트림을 실행하는 대신entrySet
, 나는 그것을 훑어보았다.keySet
이로 인해 지도 엔트리가 아닌 지도에서 값을 가져와야 하는 비용이 발생하면서 코드가 좀 더 깨끗해졌습니다.덧붙여서, 저는 처음에key -> key
첫 번째 논거로서toMap()
그리고 이것은 어떤 이유로 타입 추론 오류로 인해 실패했습니다.로 변경하다(X key) -> key
효과가 있었다Function.identity()
.
또 다른 변형은 다음과 같습니다.
static <X, Y, Z> Map<X, Z> transform1(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
Map<X, Z> result = new HashMap<>();
input.forEach((k, v) -> result.put(k, function.apply(v)));
return result;
}
이 방법에서는Map.forEach()
개울이 아니라.이것은 수집가들에게 불필요하기 때문에 지도와 함께 사용하기에는 다소 서투른 방법이기 때문에 더욱 간단하다고 생각합니다.그 이유는Map.forEach()
는 키와 값을 별도의 파라미터로 제공하지만 스트림에는 값이1개밖에 없습니다.또한 키와 맵엔트리를 그 값으로 사용할지 선택해야 합니다.부정적인 면에서는, 이것은 다른 어프로치의 풍부하고 부드러운 장점이 결여되어 있습니다. :-)
이와 같은 범용 솔루션
public static <X, Y, Z> Map<X, Z> transform(Map<X, Y> input,
Function<Y, Z> function) {
return input
.entrySet()
.stream()
.collect(
Collectors.toMap((entry) -> entry.getKey(),
(entry) -> function.apply(entry.getValue())));
}
예
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<String, Integer> output = transform(input,
(val) -> Integer.parseInt(val));
Guava의 기능은 당신이 원하는 기능으로 람다 표현과 잘 어울립니다.
Maps.transformValues(originalMap, val -> ...)
100% 기능적이고 유창해야 합니까?그렇지 않다면, 이것은 어떻습니까? 이는 거의 짧은 시간입니다.
Map<String, Integer> output = new HashMap<>();
input.forEach((k, v) -> output.put(k, Integer.valueOf(v));
(부작용을 수반하는 흐름의 수치와 죄책감을 안고 살 수 있다면)
표준 스트림 API를 강화한 My StreamEx 라이브러리는 맵 변환에 더 적합한 클래스를 제공합니다.
Map<String, Integer> output = EntryStream.of(input).mapValues(Integer::valueOf).toMap();
학습 목적으로 항상 존재하는 대체 방법은 Collector.of()를 사용하여 커스텀 컬렉터를 구축하는 것입니다.단, 여기서 toMap() JDK 컬렉터는 간결합니다(+1).
Map<String,Integer> newMap = givenMap.
entrySet().
stream().collect(Collector.of
( ()-> new HashMap<String,Integer>(),
(mutableMap,entryItem)-> mutableMap.put(entryItem.getKey(),Integer.parseInt(entryItem.getValue())),
(map1,map2)->{ map1.putAll(map2); return map1;}
));
서드파티 라이브러리를 사용해도 괜찮으시다면 my cyclops-react lib에는 Map을 포함한 모든 JDK 컬렉션 유형에 대한 확장 기능이 있습니다.맵은 '맵' 연산자를 사용하여 직접 변환할 수 있습니다(기본적으로 맵은 맵의 값에 적용됩니다).
MapX<String,Integer> y = MapX.fromMap(HashMaps.of("hello","1"))
.map(Integer::parseInt);
bimap을 사용하여 키와 값을 동시에 변환할 수 있습니다.
MapX<String,Integer> y = MapX.fromMap(HashMaps.of("hello","1"))
.bimap(this::newKey,Integer::parseInt);
선언적이고 간단한 해결책은 다음과 같습니다.
map.replaceAll((key, val) -> getUpdatedListFor(key, val));
yourMutableMap.replaceAll((key, val) return_value_of_bi_your_function); nb. 맵 상태를 변경하는 것에 주의해 주세요.그래서 이게 네가 원하는 게 아닐 수도 있어.
건배사 : http://www.deadcoderising.com/2017-02-14-java-8-declarative-ways-of-modifying-a-map-using-compute-merge-and-replace/
언급URL : https://stackoverflow.com/questions/25903137/java8-hashmapx-y-to-hashmapx-z-using-stream-map-reduce-collector
'source' 카테고리의 다른 글
Flutter.io Android 라이센스 상태 불명 (0) | 2022.08.13 |
---|---|
VueJ는 div 래퍼 없이 계산된 값을 원시 HTML로 취급합니다. (0) | 2022.08.13 |
C의 정수 배열에 대해 memset 사용 (0) | 2022.08.13 |
vue cli 3에서 생성된 프로젝트에서 개발 서버를 시작하는 중 (0) | 2022.08.13 |
Vue 라우터가 페이지를 변경할 때 Jquery 플러그인/스크립트를 로드하는 방법 (0) | 2022.08.13 |