2016-04-07 42 views
1

我是使用lambdas和流的新手。我正在嘗試打印一個ArrayList,其中刪除了重複項並進行了格式化。我知道下面的工作:在Java中的流中使用printf

list.stream().distinct().forEach(System.out::print); 

這將產生ADFJKLXZ或任何隨機字符的輸出我在列表中。不過,我想什麼我的輸出看起來像爲A,d,F,J,K,L,X,Z

我已經試過這樣:

list.stream().distinct().forEach(System.out::printf("%s, ",)); 

我想我可能還是有一些困惑on :: 爲什麼上面的代碼沒有工作,我該如何解決它?

回答

4

您正在嘗試傳遞方法引用,同時傳遞顯式參數,這是無法完成的。你可以用一個lambda表達式代替。

list.stream().distinct().forEach(x -> System.out.printf("%s, ", x)); 

這lambda表達式是一個Consumer,打印字符跟一個逗號和一個空格。

如果您仍想使用方法參考,則創建自己的方法來包裝printf調用。

public static void printWithCommaSpace(Character c) 
{ 
    System.out.printf("%s, ", c); 
} 

然後:

list.stream().distinct().forEach(YourClass::printWithCommaSpace); 
+0

這就說得通了。所以只能在沒有參數傳遞時才能使用::。 –

+2

僅當簽名與被調用的方法預期的功能接口類型相匹配時才能使用方法引用。在這種情況下,'forEach'需要一個'Consumer',它只需要一個參數。關於方法引用的任何內容都不傳遞顯式參數,因爲方法引用並不等同於實際的方法調用,而只是實現稍後可以調用的功能接口。 – rgettman

+2

實際上,當您使用形式爲'System.out :: println'的方法引用時,您已經綁定了一個值,即在'System.out'中找到的'PrintStream'實例,該方法將被調用。所以方法引用最多可以綁定一個值,它總是一個對象,方法最終會調用該對象。另請參閱[「System.out :: println」的等效lambda表達式是什麼?](http://stackoverflow.com/a/28025717/2711488) – Holger

4

因爲這不是方法引用是如何工作的,單一的參數必須匹配捕獲的價值,這是不是這裏的情況。

你如何解決它?使用lambda

list.stream().distinct().forEach(i -> System.out.printf("%s, ",i)); 

順便說一句,做它一個更簡潔的方法是使用Collectors.joining

String collect = list.stream().collect(Collectors.joining(", ")); 

現在你不要在字符串的結尾有這樣額外的逗號