以下是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()