2014-11-14 121 views
21

我正在使用Twitter4J。但我所問的問題是更一般的。我想訪問給定推文的用戶ID。目前,我有以下兩種選擇:地圖鏈方法參考

//Option 1 
stream.map(status -> status.getUser().getId()) 
     .forEach(System.out::println); 

//Option 2: 
stream.map(Status::getUser) 
     .map(User:getId) 
     .forEach(System.out::println); 

我不喜歡在第一個選項lambda表達式,也被迫調用兩個maps在第二個。有沒有辦法建立一個方法引用鏈?我知道Status::getUser::getId不起作用,但我想知道是否有其他選擇。

+1

爲什麼你不喜歡2'map'調用?你擔心表演嗎?您不必 - 流將一次處理。 –

+5

冗長。出於同樣的原因,'status.getUser()。getId()'存在,我希望像'Status :: getUser :: getId'這樣的東西存在。 – mossaab

回答

14

不,這些是做這件事的兩種方式。其他任何事情最終都會變得不那麼清晰。

但是,既然你問了,這裏有一些選項。

static<T,U,R> Function<T,R> chain(
     Function<? super T, ? extends U> f1, 
     Function<? super U, ? extends R> f2) { 
    return t -> f2.apply(f1.apply(t)); 
} 

stream.map(chain(Status::getUser, User::getId)) 

或者

static<T,R> Function<T,R> func(Function<T,R> f) { 
    return f; 
} 

stream.map(func(Status::getUser).andThen(User::getId)) 
+2

實際上,兩種方法都做了兩次調用'map'的操作,唯一的區別是流將始終使用'Function.andThen'或'Function.compose'而不是自己重新實現它(就像你的'chain'方法一樣) 。 – Holger

+1

我一直在尋找避免調用類User的東西,因爲它應該直接從'getUser'推斷出來。我接受「不是」作爲答案。 – mossaab

1

提出了兩種選擇,我傾向於使用第二,鏈接調用map()

還有其他選項,它使用內置API而不是輔助方法,如圖所示here.使用Function.compose()Function.andThen()方法,您可以鏈接函數調用。 Predicate和其他功能接口實現類似的默認方法。

stream.map(((Function<Status, User>) Status::getUser).andThen(User::getId)) 
    .forEach(System.out::println); 

備選地

Function<Status, User> toUser = Status::getUser; 
stream.map(toUser.andThen(User::getId)).forEach(System.out::println); 

的缺點是,在爲了使用這些,功能接口類型必須被明確地給出。這需要演員或任務,而且看起來有點醜陋。所以對於測繪連鎖,我通常使用多個map()調用。