2016-04-07 17 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(", ")); 

现在你不要在字符串的结尾有这样额外的逗号