我知道如何从Y
->Z
“转换”一个简单的Java列表
,即:
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
}
解决方案不应局限于字符串
->整数
。就像上面的list
示例一样,我希望调用任何方法(或构造函数)。
类似这样的通用解决方案
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));
下面是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()
的第一个参数,但由于某种原因导致类型推断错误而失败。将其更改为(Xkey)->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()
将键和值作为单独的参数给出,而流只有一个值--您必须选择是使用键还是映射条目作为该值。在缺点方面,这种方法缺乏其他html" target="_blank">方法的丰富、流畅的优点。:-)
Map<String, String> x;
Map<String, Integer> y =
x.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey(),
e -> Integer.parseInt(e.getValue())
));
它不像列表代码那么好。您不能在map()
调用中构造新的map.entry
s,因此该工作被混合到collection()
调用中。
问题内容: 我知道如何从-> “转换”一个简单的Java ,即: 现在,我想对地图进行基本相同的操作,即: 解决方案不应限于-> 。就像上面的示例一样,我想调用任何方法(或构造函数)。 问题答案: 它不如列表代码那么好。您不能在通话中构造new ,因此工作会混入通话中。
我是Java 8流的新手。请提供建议,如何转换流<代码>流 例如,我在代码中有一些流: 我怎么能做这样的事 ? 对不起,我的英语不好。
我尝试了这种方法,但得到了强制转换异常,不能将字符串转换为整数。
我有和如下代码所示: 我尝试用< code>HashMap值替换该字符串,但这不起作用,因为< code>test是最终的,不能在< code>forEach的主体中重新分配。 那么有没有用Java 8 Stream API将< code>String替换为< code>HashMap的解决方案呢?
问题内容: 是的实现,并且的构造函数接收类型参数。那么,为什么必须对其进行显式转换? 问题答案: 这是因为extends(又实现了)。您尝试将其输入。因此,它是不兼容的。 您需要将字符串属性一一输入到地图中。 例如:
问题内容: 我有arrayList 我想像这样转换为ArrayList到HashMap 请帮助我如何转换为HashMap。 问题答案: 一般的方法是遍历,然后将值插入。示例如下: