2014-11-14 13 views
21

Pracuję z Twitter4J. Ale pytanie, które zadaję, jest bardziej ogólne. Chcę uzyskać dostęp do identyfikatora użytkownika danego tweeta. Obecnie mam dwie następujące opcje:Referencje metody Łańcuch mapy

//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); 

Nie lubię wyrażenia lambda w pierwszej opcji, ani zmuszony zadzwonić dwa maps w drugim. Czy istnieje sposób na utworzenie łańcucha odwołań do metod? Wiem, że Status::getUser::getId nie działa, ale zastanawiam się, czy istnieje alternatywa.

+1

Dlaczego nie lubisz 2 "map" połączeń? Czy martwisz się wydajnością? Nie musisz - strumień zostanie przetworzony w jednym przebiegu. –

+5

Gadatliwość. Z tego samego powodu istnieje "status.getUser(). GetId()", miałem nadzieję, że istnieje coś takiego jak "Status :: getUser :: getId". – mossaab

Odpowiedz

14

Nie, to są dwa sposoby robienia tego. Wszystko inne skończyłoby się tylko mniej jasne.

Ale ponieważ pytasz, oto kilka opcji.

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)) 

Albo

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

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

Właściwie oba podejścia robią to, co dwa razy nazywa się 'map', a jedyną różnicą jest to, że strumień zawsze użyje' Function.andThen' lub 'Function.compose' zamiast ponownie implementować to samo (jak twoja metoda' chain') . – Holger

+1

Szukałem czegoś, co uniknie wywoływania klasy "Użytkownik", ponieważ powinno być wywnioskowane bezpośrednio z 'getUser'. Akceptuję "Nie" jako odpowiedź. – mossaab

1

z dwóch opcji proponowanych, staram się wykorzystać drugi, łańcuchowego połączenia do map().

Dostępne są inne opcje, które korzystają z wbudowanego interfejsu API zamiast metod pomocniczych, jak pokazano na stronie here. Metodami Function.compose() lub Function.andThen() można wywoływać łańcuchowe wywołania funkcji. Predicate i inne interfejsy funkcjonalne implementują podobne domyślne metody.

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

Alternatywnie

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

Wadą jest to, że w celu wykorzystania ich, funkcjonalny typu interfejs ma być podana w sposób jawny. To wymaga obsady lub zadania i to wygląda trochę brzydko. Tak więc w przypadku łańcucha odwzorowania zwykle używam wielu wywołań map().