" Java 8 Lambdas:实用的功能编程"有一个在peek
API中使用Stream
方法的示例。这段代码打印的艺术家国籍名称以"":
Set<Nationality> nationalities = album.getMusician()
.filter(artist -> artist.getName().startsWith("The"))
.map(artist -> artist.getNationality())
.peek(nation -> System.out.println(nation))
.collect(Collectors.toList());
我想用方法引用重写此代码:
Set<Nationality> nationalities = album.getMusician()
.filter(artist -> artist.getName().startsWith("The"))
.map(Artist::getNationality)
.peek(System.out::println)
.collect(Collectors.toList());
是否有任何重写filter(artist -> artist.getName().startsWith("The"))
的解决方案?
答案 0 :(得分:6)
您需要创建一个单独的方法,该方法接受一个Artist并返回一个布尔值:
private boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(this::nameStartsWithThe)
或使用静态方法:
private static boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(MyClass::nameStartsWithThe)
答案 1 :(得分:2)
您需要构成这两种方法的东西。有一些组合方法的方法(IntUnaryOperator
有compose
和andThen
方法,可以将两个IntUnaryOperator
组成一个新的IntUnaryOperator
)。但我发现的那些似乎都专门用于某些类型的功能接口;为每一对可能的功能接口类型定义compose
方法会过于笨拙。
我确实得到了一些可以构成Function
和Predicate
以获得新Predicate
的内容:
static <T,U> Predicate<T> functionPredicate(Function<T,U> func, Predicate<U> pred) {
return obj -> pred.test(func.apply(obj));
}
也就是说,它可以构成一个谓词,该谓词对T
的函数进行操作,该函数使用T
并返回U
,以及对U
进行操作的谓词。除了startsWith
需要另一个参数之外,这将几乎对您的示例起作用。但这确实有效:
static boolean startsWithThe(String s) {
return s.startsWith("The");
}
Predicate<Artist> pred = functionPredicate(Artist::getName, ThisClass::startsWithThe);
其中ThisClass
是包含startsWithThe
的任何类。这有效。如果你想避免编写一个新方法(比如startsWithThe
),你可能会写一个参数化的谓词&#34;通用方法,以便您编写类似
Predicate<Artist> pred = functionPredicate(Artist::getName, parameterizedPredicate(String::startsWith, "The"));
但我还没试过。
因此,似乎可以提出某些,它可以让你使用方法引用而不是lambdas。我怀疑它是否值得。对我来说,方法参考只是某些种类的lambda的简写;除非你能用一个简单的方法参考做你想做的事情,我认为使用lambda足够简洁明了,而且你不需要添加像我functionPredicate
这样的额外装备。方法。我已经看到了几个问题,例如&#34;我如何使用方法参考而不是lambda?&#34;,老实说,我不明白为什么。
答案 2 :(得分:0)
无法用方法参考替换该行。
方法引用的工作原理是整个lambda表达式中只使用了一个对象,编译器可以使用目标类型推断它(引用无关紧要,类型可以推断)。
所以,
artist -> artist.getNationality()
替换为
Artist::getNationality
此处Artist::getNationality
方法与目标类型匹配,无需任何进一步的信息。
在artist -> artist.getName().startsWith("The")
的情况下,lambda表达式中有两个方法调用。订单,参数很重要,必须指定。
看起来好像应该推断artist
引用,但是编译器不知道应该调用startsWith("The")
方法的对象。
希望这有帮助。