[英]Replacing chained method call using method reference
“Java 8 Lambdas:實用功能編程”有一個在Stream
API中使用peek
方法的例子。 這段代碼打印名稱以“The”開頭的藝術家國籍:
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"))
解決方案filter(artist -> artist.getName().startsWith("The"))
?
您需要創建一個單獨的方法,該方法接受一個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)
你需要一些組成這兩種方法的東西。 有一些組合方法的方法( 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
),你可能會編寫一個“參數化謂詞”泛型方法,這樣你就可以寫一些像
Predicate<Artist> pred = functionPredicate(Artist::getName, parameterizedPredicate(String::startsWith, "The"));
但我沒試過。
所以似乎有可能提出一些讓你使用方法引用而不是lambdas的東西。 我懷疑它是否值得。 對我來說,方法參考只是某些種類的lambda的簡寫; 除非你能用一個簡單的方法引用做你想做的事情,我認為使用lambda是簡潔明了的,你不需要像我的functionPredicate
方法那樣添加所有額外的rigmarole。 我已經看過幾個問題,比如“我怎么能用這個方法參考而不是lambda?”,老實說我不明白為什么。
無法用方法引用替換該行。
方法參考通過使用以下事實來工作:在整個lambda表達式中只使用一個對象,並且編譯器可以使用目標類型推斷它(引用無關緊要並且可以推斷類型)。
所以,
artist -> artist.getNationality()
被替換為
Artist::getNationality
這里Artist::getNationality
方法與目標類型匹配,無需任何進一步的信息。
如果是artist -> artist.getName().startsWith("The")
,則lambda表達式中有兩個方法調用。 訂單,參數很重要,必須指定。
看起來好像應該推斷出artist
引用,但是編譯器不會知道應該調用startsWith("The")
方法的對象。
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.