java 在返回之前过滤集合流内的集合流

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30196997/
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-11-02 16:38:56  来源:igfitidea点击:

Filtering collection stream inside collection stream before returning

javalambdacollectionsjava-8java-stream

提问by Martin M J

Background information

背景资料

I've got the following classes:

我有以下课程:

Insurance

保险

public class Insurance {
    ...
}

Customer

顾客

public class Customer {
    private List<Insurance> insurances;

    public List<Insurance> getInsurances() {
        return insurances;
    }
    ...
}

CustomerRegistry

客户登记处

public class CustomerRegistry {
    private List<Customer> customers;
    ...
}

as well as this helper method, which reduces a List<Predicate<T>>into a single Predicate<T>:

以及这个辅助方法,它将 aList<Predicate<T>>简化为单个Predicate<T>

public Predicate<T> reducePredicates(List<Predicate<T>> predicates) {
    return predicates.stream()
                     .reduce(Predicate::and)
                     .orElse(p -> true);
}


The problem

问题

What I want to do is get a list of insurances that match a list of filters, belonging to customers that match a list of filters. If this is unclear, the below code will hopefully clarify.

我想要做的是获取与过滤器列表匹配的保险列表,属于与过滤器列表匹配的客户。如果这不清楚,下面的代码有望澄清。

Method is inside CustomerRegistryclass above.

方法在CustomerRegistry上面的类中。

public List<Insurance> findInsurances(List<Predicate<Customer>> cusPredicates,
List<Predicate<Insurance>> insPredicates) {

    List<Insurance> matches = new LinkedList<>();
    customers.stream()
             .filter(reducePredicates(cusPredicates)
             .forEach(cus -> cus.getInsurances()
                               .stream()
                               .filter(reducePredicates(insPredicates))
                               .forEach(cus -> matches.add(cus)))
    return matches;
}

Is there a way to do this without the matcheslist? Can I perform some sort of reduction, so that the matching insurances are returned directly (i.e. not being added to a temporary collection like matches)?

有没有办法在没有matches列表的情况下做到这一点?我是否可以执行某种减少,以便直接返回匹配的保险(即不会添加到像 那样的临时集合中matches)?

采纳答案by JB Nizet

Use flatMap():

使用 flatMap():

customers.stream()
         .filter(reducePredicates(cusPredicates))
         .flatMap(cus -> cus.getInsurances().stream())
         .filter(reducePredicates(insPredicates))
         .collect(Collectors.toList())

Or better, to avoid reducing the predicates over and over again:

或者更好的是,为了避免一遍又一遍地减少谓词:

Predicate<Customer> customerPredicate = reducePredicates(cusPredicates);
Predicate<Customer> insurancePredicate = reducePredicates(insPredicates);
List<Insurance> = 
    customers.stream()
             .filter(customerPredicate)
             .flatMap(cus -> cus.getInsurances().stream())
             .filter(insurancePredicate)
             .collect(Collectors.toList())