Java 8 Lambda - 两个列表的交集

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31683375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:25:25  来源:igfitidea点击:

Java 8 Lambda - Intersection of Two Lists

javalambdajava-8intersection

提问by Reddy

I am trying to find intersectionof two lists based on some condition and doing some steps. Couldn't find a way to do it (in learning stage) :)

我试图intersection根据某些条件查找两个列表并执行一些步骤。找不到方法(在学习阶段):)

Double totalAmount = 0.00d;
Double discount = 0.00d;


List<OrderLineEntry> orderLineEntryList = orderEntry.getOrderReleases().stream()
    .flatMap(orderReleaseEntry -> orderReleaseEntry.getOrderLines().stream())
    .filter(orderLineEntry -> orderLineEntry.getStatus().equals("PP") || orderLineEntry.getStatus().equals("PD"))
    .collect(Collectors.toList());

for (OrderLineEntry orderLineEntry : orderLineEntryList) {
    for (SplitLineEntry splitLineEntry : splitReleaseEntry.getLineEntries()) {
        if (splitLineEntry.getOrderLineId().equals(orderLineEntry.getId()) && splitLineEntry.getStatusCode() != "PX") {
            totalAmount += orderLineEntry.getFinalAmount();
            couponDiscount += orderLineEntry.getCouponDiscount() == null ? 0.00d : orderLineEntry.getCouponDiscount();
        }
    }
}

As you see, the logic is simple

如您所见,逻辑很简单

Get All items from order based on some filter listand intersect with another listand do some stuff.

根据某些过滤器从订单中获取所有项目list并与另一个相交list并做一些事情。

采纳答案by Silas Reinagel

The simplest approach is this:

最简单的方法是这样的:

List<T> intersect = list1.stream()
                         .filter(list2::contains)
                         .collect(Collectors.toList());

回答by Peter Lawrey

I need to compare them on assume list1.id == list2.fk_id

我需要在假设 list1.id == list2.fk_id 上比较它们

First build up a set of the fk_id;

首先建立一组fk_id;

Set<Integer> orderLineEntrSet = orderEntry.getOrderReleases().stream()
    .flatMap(orderReleaseEntry ->
orderReleaseEntry.getOrderLines().stream())
    .filter(orderLineEntry -> { 
            String s = orderLineEntry.getStatus(); 
            return "PP".equals(s) || "PD".equals(s); 
    })
    .map(e -> e.getId())
    .collect(Collectors.toSet());

double[] totalAmount = { 0.0 };
double[] couponDiscount = { 0.0 };
orderLineEntryList.stream()
    .flatMap(sre -> sre.getLineEntries().stream())
    .filter(ole -> orderLineEntrySet.contains(ole.getOrderLineId())
    .filter(ole -> !"PX".equals(ole.getStatusCode()))
    .forEach(ole -> {
            totalAmount[0] += ole.getFinalAmount();
            if (ole.getCouponDiscount() != null)
                couponDiscount[0] += ole.getCouponDiscount();
        });

You can avoid using a reference to an array object by using reduce function. e.g. see how Collectors.averagingDouble is implemented. But I find this more complicated.

您可以通过使用 reduce 函数来避免使用对数组对象的引用。例如,看看 Collectors.averagingDouble 是如何实现的。但我觉得这更复杂。

Note: this is O(N) by using a set of ids rather than using a list of matching ids which would be O(N^2)

注意:这是 O(N) 通过使用一组 id 而不是使用匹配 id 的列表,这将是 O(N^2)

回答by psekar

List<T> intersect = list1.stream().filter(set1::contains).collect(Collectors.toList());

List<T> intersect = list1.stream().filter(set1::contains).collect(Collectors.toList());

This will work as long as Tis a String, Integer, Float, etc. where the equals and HashCode methods are straightforward. But if the Tis a custom object, we need to implement HashCode & equals

这将工作,只要TStringIntegerFloat等在那里的equals和hashCode方法非常简单。但是如果T是自定义对象,我们需要实现HashCode & equals