仅当allMatch筛选器和流程流在Java中匹配一次时收集流

仅当allMatch筛选器和流程流在Java中匹配一次时收集流,java,java-stream,Java,Java Stream,我有以下流代码: List<Data> results = items.stream() .map(item -> requestDataForItem(item)) .filter(data -> data.isValid()) .collect(Collectors.toList()); Data requestDataForItem(Item item) { // call another service here } List resu

我有以下流代码:

List<Data> results = items.stream()
   .map(item -> requestDataForItem(item))
   .filter(data -> data.isValid())
   .collect(Collectors.toList());

Data requestDataForItem(Item item) {
   // call another service here
}
List results=items.stream()
.map(项目->requestDataForItem(项目))
.filter(数据->数据.isValid())
.collect(Collectors.toList());
数据请求DataForItem(项目){
//在这里呼叫其他服务
}
问题是我想打电话
requestDataForItem
仅当流中的所有元素都有效时。 例如 如果第一项无效,我不想调用流中的任何元素

流API中有
.allMatch
, 但它返回一个
布尔值。
我想做与
.allMatch
相同的事情
。在所有内容匹配时收集结果。
另外,我只想处理流一次,
有了两个循环,这很容易


Java Streams API是否可以实现这一点?

实现两步流程:

  • 测试allMatch是否返回true
  • 如果返回true,则使用第二个流执行collect

  • 理论上可以使用
    .allMatch
    然后在
    返回true时进行收集。allMatch
    返回true后,将对收集进行两次处理。无法直接使用streams API执行您正在尝试执行的操作

    您可以创建一个方法来完成这项工作,并简单地将集合传递给它,而不是使用流API。与使用流API相比,这稍微不那么优雅,但由于只处理一次集合,因此效率更高

    List<Data> results = getAllIfValid(
             items.stream().map(item -> 
                 requestDataForItem(item).collect(Collectors.toList())
    );
    
    public List<Data> getAllIfValid(List<Data> items) {
        List<Data> results = new ArrayList<>();
        for (Data d : items) {
            if (!d.isValid()) {
                return new ArrayList<>();
            }
            results.add(d);
        }
        return results;
    }
    
    List results=getAllIfValid(
    items.stream().map(项->
    requestDataForItem(item).collect(Collectors.toList())
    );
    公共列表getAllIfValid(列表项){
    列表结果=新建ArrayList();
    用于(数据d:项目){
    如果(!d.isValid()){
    返回新的ArrayList();
    }
    结果:添加(d);
    }
    返回结果;
    }
    
    如果每个元素都通过并且只处理一次
    items
    集合,则此操作将返回所有结果。如果任何项未通过
    isValid()
    检查,则它将返回一个空列表,因为您需要全部或全部。只需检查返回的集合是否为空,以查看是否所有项都通过了
    isValid()
    检查。

    试试这个

    List<Data> result = new ArrayList<>();
    boolean allValid = items.stream()
        .map(item -> requestDataForItem(item))
        .allMatch(data -> data.isValid() && result.add(data));
    if (!allValid)
        result.clear();
    
    List result=new ArrayList();
    布尔值allValid=items.stream()
    .map(项目->requestDataForItem(项目))
    .allMatch(数据->数据.isValid()&&result.add(数据));
    如果(!allValid)
    result.clear();
    
    这将是Java 9的工作:

    List<Data> results = items.stream()
        .map(item -> requestDataForItem(item))
        .takeWhile(data -> data.isValid())
        .collect(Collectors.toList());
    

    只需检查
    results.size()==items.size()
    。谢谢。我已经更新了我的问题。两个步骤的过程很清楚,但它是多余的。谢谢你的想法。API不保证
    allMatch
    会按遭遇顺序计算所有元素。
    List<Data> results = new ArrayList<>();
    for(Item item: items) {
        Data data = requestDataForItem(item);
        if(!data.isValid()) break;
        results.add(data);
    }