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

时间:2017-04-19 14:38:45

标签: java lambda java-8 java-stream

此问题可视为基于java 8 nested streams

假设我Batch BasketItem s:

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

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

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

我想用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;
    }
}

我该怎么做?

我想去的第一步:

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'
    }
}

非常感谢。

3 个答案:

答案 0 :(得分:4)

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

使用findAny代替findFirst的好处是findFirst不适用于并行流。因此,如果您要并行执行上述操作,则需要将stream()方法替换为parallel()

答案 1 :(得分:3)

要消除这两个循环,您可以使用flatMap生成所有Stream<Item> s中所有Item的{​​{1}}:

Basket

答案 2 :(得分:3)

  1. 使用flatMap获取嵌套列表,提取每个List<Item>,将其转换为Stream<Item>,并将所有子流合并在一起。
  2. 使用filter忽略不匹配的元素。
  3. 使用findFirst仅获取第一次出现并停止处理
  4. 如果未发现 someValue ,请使用orElseThrow抛出异常。
  5. 你去吧

    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"));
        }
    }