如何通过使用Lambda表达式的.reduce()方法来减少给定的列表 [英] How to reduce given list by using Lambda expression .reduce() method

查看:197
本文介绍了如何通过使用Lambda表达式的.reduce()方法来减少给定的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 列表与LT;整数>整数= Arrays.asList(1,2,3,5,6,8,9,10); $()
integer()。filter((integer) - > integer%2 == 0).collect(Collectors.toList());

如上所示整数是一个List,从中我们只需要过滤偶数。我可以通过使用 .filter()方法来实现。但是,是否有可能通过 .reduce()方法实现。希望 .reduce()方法通过执行给定的BynaryOperation过滤掉所有其他元素并返回缩小列表。



如果我的理解在 .reduce()方法上是不正确的,请告诉我这个方法究竟做了什么。

解决方案

你对减少的理解是错误的。 reduce 将对所有元素重复应用一个函数来得到一个结果

你似乎认为减少像做

  1,2,3,5,6,8 ,9,10 
││││││││
└op┘└op┘└op┘└op┘
││││
结果列表

事实上,它确实是

  1,2,3,5,6,8,9,10 
│││││││
└op┘└op┘ └op┘└op┘
│││|$ b $b└─op──└─op──
││
└────op────── b $ b│
最终结果值

虽然这是一个概念性视图,操作顺序是未指定的。顺序执行将像(((1 op 2)op 3)op 4)... ,而并行执行将像上面的树和部分顺序执行。




您可以滥用 reduce 创建一个结果列表,如果你首先将每个元素转换成一个 List ,然后使用连接每个列表的列表操作,然而,这有两个问题:




  • 它没有提供期望的跳过原始列表的每一个元素逻辑。如果你看一下上面的树,应该清楚的是,在每个可能的执行场景中都不可能建立一个正确的 op 函数

  • 创建临时列表并连接它们是非常低效的。

    $ b 后一点可以通过使用 collect ,这是一个可变的减少,因此,允许您使用可添加项目的可变列表,但是它并没有解决第一个问题,包括所需的过滤器将违反合同,只能在顺序执行。

    所以解决方案是定义一个过滤器对于源列表范围内的所有元素,然后是使用 collect 创建结果列表的可变缩减,以及大惊喜,这正是您原始代码的作用:

      ... .filter(integer  - > integer%2 == 0).collect(Collectors.toList()); 


    List<Integer> integers = Arrays.asList(1, 2, 3, 5, 6, 8, 9, 10);
    integers.stream().filter((integer) -> integer % 2 == 0).collect(Collectors.toList());
    

    As shown above integers is a List, from which we need to filter only even numbers. I can achieve by using .filter() method. But, is there any possibility to achieve the same with .reduce() method. Hope, .reduce() method filtered out all the other elements by performing given BynaryOperation and return reduced list.

    If my understanding is not correct on .reduce() method, please let me know what exactly this method do.

    解决方案

    Your understanding of reduction is wrong. reduce will apply a function on all elements repeatedly to get one single result.

    You seem to think of reduce like doing

    1, 2, 3, 5, 6, 8, 9, 10
    │  │  │  │  │  │  │  │
    └op┘  └op┘  └op┘  └op┘
      │     │     │     │
        result list
    

    whereas, in fact, it does

    1, 2, 3, 5, 6, 8, 9, 10
    │  │  │  │  │  │  │  │
    └op┘  └op┘  └op┘  └op┘
      │    │      │    │
      └─op─┘      └─op─┘
         │          │
         └────op────┘
               │
       final result value
    

    Though, this is a conceptional view, the exact order of operations is unspecified. A sequential execution will be like (((1 op 2) op 3) op 4)… while a parallel execution will be a mixture of an execution like the tree above and partial sequential execution(s).


    You can abuse reduce to create a result list if you first convert each element into a List and then use a list operation which concatenates each list, however, there are two problems with this:

    • It doesn’t provide the desired "skip each second element (of the original list)" logic; if you look at the tree above, it should become clear, that it is impossible to formulate a correct op function which does that in every possible execution scenario
    • creating temporary lists and concatenating them is very inefficient

    The latter point can be solved by using collect, which is a mutable reduction, hence, allows you to use mutable lists to which you can add items, however, it does not address the first point, including the desired filter would violate the contract and only work in a sequential execution.

    So the solution is to define a filter for all elements in the scope of the source list, followed by a mutable reduction to create the result list using collect, and, big surprise, that’s exactly what you original code does:

    … .filter(integer -> integer % 2 == 0).collect(Collectors.toList());
    

    这篇关于如何通过使用Lambda表达式的.reduce()方法来减少给定的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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