Ben*_*n M 188 java mapreduce java-8 java-stream collectors
我知道如何List
从Y
- > "转换"一个简单的Java Z
,即:
List<String> x;
List<Integer> y = x.stream()
.map(s -> Integer.parseInt(s))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
现在我想用Map做基本相同的事情,即:
INPUT:
{
"key1" -> "41", // "41" and "42"
"key2" -> "42 // are Strings
}
OUTPUT:
{
"key1" -> 41, // 41 and 42
"key2" -> 42 // are Integers
}
Run Code Online (Sandbox Code Playgroud)
解决方案不应限于String
- > Integer
.就像List
上面的例子一样,我想调用任何方法(或构造函数).
Joh*_*ica 336
Map<String, String> x;
Map<String, Integer> y =
x.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey(),
e -> Integer.parseInt(e.getValue())
));
Run Code Online (Sandbox Code Playgroud)
它不如列表代码那么好.您无法Map.Entry
在map()
呼叫中构建新的s,因此工作会混合到collect()
呼叫中.
Stu*_*rks 34
以下是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))));
}
Run Code Online (Sandbox Code Playgroud)
这里有几点.首先是在泛型中使用通配符; 这使得功能更加灵活.例如,如果您希望输出映射具有输入映射键的超类的键,则需要使用通配符:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
Run Code Online (Sandbox Code Playgroud)
(地图的值也有一个例子,但它确实是人为的,我承认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;
}
Run Code Online (Sandbox Code Playgroud)
这使用Map.forEach()
而不是流.我认为这更简单,因为它省去了收藏家,这些收藏家与地图一起使用有些笨拙.原因是Map.forEach()
将键和值作为单独的参数,而流只有一个值 - 您必须选择是使用键还是映射条目作为该值.从缺点来看,这缺乏其他方法的丰富,流动的优点.:-)
Sot*_*lis 12
像这样的通用解决方案
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())));
}
Run Code Online (Sandbox Code Playgroud)
例
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));
Run Code Online (Sandbox Code Playgroud)
Ale*_*uss 12
Guava的功能Maps.transformValues
是你正在寻找的,它与lambda表达式很好地配合:
Maps.transformValues(originalMap, val -> ...)
Run Code Online (Sandbox Code Playgroud)
Luk*_*der 10
它绝对必须100%功能和流畅吗?如果没有,那么这个怎么样,就像它得到的一样短:
Map<String, Integer> output = new HashMap<>();
input.forEach((k, v) -> output.put(k, Integer.valueOf(v));
Run Code Online (Sandbox Code Playgroud)
我的StreamEx库增强了标准流API,提供了一个EntryStream
更适合转换地图的类:
Map<String, Integer> output = EntryStream.of(input).mapValues(Integer::valueOf).toMap();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
149118 次 |
最近记录: |