Java - forEach的基本流使用

时间:2016-11-22 16:51:32

标签: java java-stream

我有一个名为Data的类,它只有一个方法:

public boolean isValid()

我有一个List Data,我想通过Java 8流循环它们。我需要计算此valid中有多少Data List个对象,并且只打印valid条目。

下面是我走了多远,但我不明白怎么做。

List<Data> ar = new ArrayList<>();
...
// ar is now full of Data objects.
...

int count = ar.stream()
            .filter(Data::isValid)
            .forEach(System.out::println)
            .count(); // Compiler error, forEach() does not return type stream.

我的第二次尝试:(可怕的代码)

List<Data> ar = new ArrayList<>();
...
// Must be final or compiler error will happen via inner class.
final AtomicInteger counter = new AtomicInteger();
ar.stream()
    .filter(Data:isValid)
    .forEach(d -> 
    {
        System.out.println(d);
        counter.incrementAndGet();
    };
System.out.printf("There are %d/%d valid Data objects.%n", counter.get(), ar.size());

2 个答案:

答案 0 :(得分:5)

如果您不需要包含有效和无效对象混合的原始ArrayList,则可以稍后执行Collection操作而不是Stream操作:

ar.removeIf(d -> !d.isValid());
ar.forEach(System.out::println);
int count = ar.size();

否则,您可以像

一样实现它
List<Data> valid = ar.stream().filter(Data::isValid).collect(Collectors.toList());
valid.forEach(System.out::println);
int count = valid.size();

为多次需要的东西存储并不是那么糟糕。如果列表非常大,您可以使用

将存储内存减少(通常)因子32
BitSet valid = IntStream.range(0, ar.size())
    .filter(index -> ar.get(index).isValid())
    .collect(BitSet::new, BitSet::set, BitSet::or);
valid.stream().mapToObj(ar::get).forEach(System.out::println);
int count = valid.cardinality();

当然,你也可以使用

int count = 0;
for(Data d: ar) {
    if(d.isValid()) {
        System.out.println(d);
        count++;
    }
}

答案 1 :(得分:4)

Peek与foreach类似,只是它允许你继续流。

ar.stream().filter(Data::isValid)
            .peek(System.out::println)
            .count();