如何使用Java 8流将地图的键+值转换为使用接收两个参数的函数的新值?

时间:2016-09-25 13:11:19

标签: java java-8 java-stream

我有一个静态方法String Converter.convert(String, Integer)

我还有一张地图:Map<String, Integer> map

我希望在地图上运行并使用convert方法将每个条目转换为字符串,并继续使用每个转换后的字符串。

我可以这样做:

map.entrySet().stream().map(e -> Converter.convert(e.getKey(), e.getValue()))....;

有没有办法更直观?如下所示?

map.stream(Converter::convert)... ...

map.stream((k, v) -> Converter.convert(k, v)))... ...

2 个答案:

答案 0 :(得分:5)

您可以在某个实用程序类中创建适配器静态方法,如下所示:

public class Functions {
    public static <K, V, R> Function<Map.Entry<K, V>, R> entryFunction(
            BiFunction<? super K, ? super V, ? extends R> fn) {
        return entry -> fn.apply(entry.getKey(), entry.getValue());
    }
}

现在您可以像这样使用它:

import static Functions.*;

map.entrySet().stream().map(entryFunction(Converter::convert))...

另一种解决方案是使用一些扩展Java 8 Stream API的第三方库。其中一个库是我写的免费StreamEx库。它包含一个实现EntryStream<K, V>的特殊类Stream<Entry<K, V>>,并提供其他方便的方法,包括mapKeyValue,这是您需要的方法:

EntryStream.of(map).mapKeyValue(Converter::convert)...

答案 1 :(得分:0)

这和你将会得到的一样好。

如果以Converter::convert作为参数,您的Map.Entry<String, Integer>方法将有效。我建议不要这样做,因为它会对在非映射上下文中使用转换器产生负面影响。

如果您使用Map.forEach方法,那么您的两个参数lambda建议将起作用,但是这不能用于您正在进行的操作。当您取出流时,您有一个Stream<Map.Entry<String, Integer>>。虽然在这种情况下,两个arg lambda可能有意义,但编译器无法知道如何将Map.Entry转换为两个参数。