Java 8 嵌套流:在最后一个流中返回一个值

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

Java 8 nested streams : return a value in last stream

javalambdajava-8java-stream

提问by Dapangma

This question can be considered as based on java 8 nested streams

这个问题可以被认为是基于java 8 嵌套流

Suppose I have a Batchwith Baskets with Items :

假设我有一个Batchwith Baskets with Items :

public class Batch {
    private List<Basket> baskets;
}

public class Basket {
    private List<Item> items; 
}

public class Item {
    private String property;
    private int value;
}

I would like to rewrite this method with Java 8 streams.

我想用 Java 8 流重写这个方法。

public class SomeService {
    public int findValueInBatch(Batch batch) {
        for (Basket basket : batch.getBaskets()) {
            for (Item item : basket.getItems()) {
                if (item.getProperty().equals("someValue") {
                    return item.getValue();
                }
            }
        }
        return 0;
    }
}

How should I do it ?

我该怎么做?

First step to where I'd like to go :

我想去的地方的第一步:

public int findValueInBatch(Batch batch) {
    for (Basket basket : batch.getBaskets()) {
        basket.getItems().stream()
            .filter(item -> item.getProperty.equals("someValue") 
            .findFirst()
            .get();
            // there I should 'break'
    }
}

Thanks a lot.

非常感谢。

回答by Avneet Paul

baskets.stream()
            .flatMap(basket -> basket.getItems().stream())
            .filter(item -> item.equals("someValue"))
            .findAny()
            .orElseThrow(NoSuchElementException::new);

The advantage of using findAnyinstead of findFirstis that findFirstdoesn't work with parallel streams. Therefore, if you want to parallelize the above operation all you'll need to do is replace the stream()method with parallel()

使用findAny而不是的优点findFirstfindFirst不适用于并行流。因此,如果您想并行化上述操作,您需要做的就是将stream()方法替换为parallel()

回答by Anthony Raymond

  1. Use flatMapto get ride of nested lists, extract each List<Item>and merge them into a Stream<Item>, it acts like all substream were merged together.
  2. Use filterto ignore the non matching elements.
  3. Use findFirstto get the first occurence only and stop processing
  4. Use orElseThrowto throw an exception if no occurence of someValuewere found.
  1. 使用flatMap得到嵌套列表的顺风车,提取每个List<Item>并将它们合并成一个Stream<Item>,它就像所有子合并在一起。
  2. 使用filter忽略不匹配元素。
  3. 用于findFirst仅获取第一次出现并停止处理
  4. 用于orElseThrow在未找到someValue 时抛出异常。

Here you go

干得好

public class SomeService {
    public int findValueInBatch(Batch batch) {
        return batch.getBaskets().stream()
            .flatMap(basket -> basket.getItems().stream())
            .filter(item -> item.getProperty.equals("someValue"))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("value not found"));
    }
}

回答by Eran

To eliminate both loops you can use flatMapto produce a Stream<Item>of all the Items of all the Baskets :

要消除这两个循环,您可以使用flatMap生成Stream<Item>所有Items 的所有Baskets 的 a :

return batch.getBaskets()
            .stream()
            .flatMap(b -> b.getItems().stream())
            .filter(item -> item.getProperty.equals("someValue"))
            .findFirst()
            .orElse(some default value); // using .get() would throw an exception
                                         // if no match is found