我有一个名为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());
答案 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();
为多次需要的东西存储并不是那么糟糕。如果列表非常大,您可以使用
将存储内存减少(通常)因子32BitSet 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();