如何在Java 8中使用方法引用进行Map合并? [英] How to use method reference in Java 8 for Map merge?

查看:463
本文介绍了如何在Java 8中使用方法引用进行Map合并?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两种形式的调用collect操作,都返回相同的结果,但我仍然不能完全依赖方法引用并需要一个lambda。

I have following 2 forms of calling a collect operation, both return same result, but I still cannot depend fully on method references and need a lambda.

<R> R collect(Supplier<R> supplier,
          BiConsumer<R,? super T> accumulator,
          BiConsumer<R,R> combiner)

为此,请考虑包含100个随机数的以下流

For this consider the following stream consisting on 100 random numbers

List<Double> dataList = new Random().doubles().limit(100).boxed()
            .collect(Collectors.toList());

1)以下示例使用纯lambda

1) Following example uses pure lambdas

Map<Boolean, Integer> partition = dataList.stream()
            .collect(() -> new ConcurrentHashMap<Boolean, Integer>(),
(map, x) ->
{
    map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, (map, map2) ->
{
    map2.putAll(map);
});

2)尝试使用方法引用但第二个参数仍需要lambda

2) Following tries to use method references but 2nd argument still requires a lambda

Map<Boolean, Integer> partition2 = dataList.stream()
            .collect(ConcurrentHashMap<Boolean, Integer>::new, 
(map, x) ->
{
    map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, Map::putAll);

如何在java 8中重写collect方法的第二个参数来使用方法引用而不是lambda for这个例子?

How can I rewrite 2nd argument of collect method in java 8 to use method reference instead of a lambda for this example?

System.out.println(partition.toString());
System.out.println(partition2.toString());
{false=55, true=45}
{false=55, true=45}


推荐答案

如果现有方法完全按照预期的方法执行,方法引用是一个方便的工具。如果你需要改编或附加操作,除了当你认为lambda表达式是那种语法时,方法引用没有特殊的语法来支持它。

A method reference is a handy tool if you have an existing method doing exactly the intended thing. If you need adaptations or additional operations, there is no special syntax for method references to support that, except, when you consider lambda expressions to be that syntax.

当然,您可以在类中创建一个新方法来执行所需的操作并创建一个方法引用,这是在代码复杂性提升时正确的方法,因为它将获得一个有意义的名称并变得可测试。但是对于简单的代码片段,您可以使用lambda表达式,这对于相同的结果来说只是一种更简单的语法。从技术上讲,没有区别,除了编译器生成的持有lambda表达式主体的方法将被标记为合成。

Of course, you can create a new method in your class doing the desired thing and create a method reference to it and that’s the right way to go when the complexity of the code raises, as then, it will get a meaningful name and become testable. But for simple code snippets, you can use lambda expressions, which are just a simpler syntax for the same result. Technically, there is no difference, except that the compiler generated method holding the lambda expression body will be marked as "synthetic".

在你的例子中,你甚至不能使用 Map :: putAll 作为合并函数,因为它会覆盖第一个映射的所有现有映射,而不是合并值。

In your example, you can’t even use Map::putAll as merge function, as that would overwrite all existing mappings of the first map instead of merging the values.

正确的实现看起来像

Map<Boolean, Integer> partition2 = dataList.stream()
    .collect(HashMap::new, 
             (map, x) -> map.merge(x < 0.5, 1, Integer::sum),
             (m1, m2) -> m2.forEach((k, v) -> m1.merge(k, v, Integer::sum)));

但您不需要自己实施。 收藏家类中已经提供了适当的内置收藏家:

but you don’t need to implement it by yourself. There are appropriate built-in collectors already offered in the Collectors class:

Map<Boolean, Long> partition2 = dataList.stream()
    .collect(Collectors.partitioningBy(x -> x < 0.5, Collectors.counting()));

这篇关于如何在Java 8中使用方法引用进行Map合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆