다음은 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()
키와 값을 별도의 매개 변수로 제공하는 반면 스트림에는 하나의 값만 있으므로 키 또는 맵 항목을 해당 값으로 사용할지 여부를 선택해야하기 때문입니다. 마이너스 측면에서는 다른 접근 방식의 풍부하고 유선형의 장점이 부족합니다. :-)
e -> e.getKey()
로Map.Entry::getKey
. 그러나 그것은 맛 / 프로그래밍 스타일의 문제입니다.