Java - forEach的基本流使用

Hat*_*end 0 java java-stream

我有一个叫做Data只有一种方法的类:

public boolean isValid()
Run Code Online (Sandbox Code Playgroud)

我有一个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.
Run Code Online (Sandbox Code Playgroud)

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

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());
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 5

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

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

否则,你可以实现它

List<Data> valid = ar.stream().filter(Data::isValid).collect(Collectors.toList());
valid.forEach(System.out::println);
int count = valid.size();
Run Code Online (Sandbox Code Playgroud)

拥有多次需要的存储空间并不是那么糟糕.如果列表非常大,则可以使用(通常)因子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();
Run Code Online (Sandbox Code Playgroud)

当然,你也可以使用

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