2016-11-22 101 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