2016-11-22 68 views
0

的使用我有一个叫Data类,只有一个方法:爪哇 - 基本流的forEach

public boolean isValid() 

我有DataList,我想通过Java 8个流通过他们循环。我需要计算此List中有多少个validData对象,并只打印出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()); 
+1

是'peek'或'收集'到一个'List',得到它的'size'并打印出来。 –

回答

4

PEEK是相似的foreach,但它可以让你继续流。

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

为什么我会使用'forEach'呢? – Hatefiend

+0

@Hatefiend当你想迭代一个列表时,你使用foreach,对每个对象执行一些操作并离开。 假设您想计算一系列客户的总利息。你可以使用foreach和每个对象调用'calculateInterest()'。 这样做的结果反正保存在原始客户对象上,所以您不必收集它。 –

+0

但是,通过这个逻辑,我可以做'list.peek(x - > x.calculateInterest();};不是吗?它与forEach() – Hatefiend

5

如果您不需要原来ArrayList,含有效和无效的对象的混合,稍后,您可能只需执行,而不是流操作的集合操作:

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++; 
    } 
} 
+0

整洁的解决方案(像往常一样),还有一个问题,32位在哪里出现在这里?它不像我们真正知道的数据内部和那个类的权重 – Eugene

+0

@Eugene:'BitSet'每个条目只使用一个位,而一个'ArrayList'存储每个条目的引用,它通常是32位(要么与体系结构相匹配,要么由于使用了压缩的OOP),这不是关于每个对象的开销,而是这些数据结构*尺寸*大尺寸。当然,我们应该小心对内部的假设,但是某些实现类即使在其名称(“位”或“数组”)中也具有其基本性质,以允许开发人员作出适当的选择。该因子可能是64而不是32,但这就是为什么我写“典型地”... – Holger

+0

,所以32来自参考存储器和BitSet中的一个单独位之间的差异。将这个因素称为*浅*差,而不是*深*差是否合适? – Eugene