2014-11-14 4 views
21

Я работаю с Twitter4J. Но вопрос, который я задаю, более общий. Я хочу получить доступ к идентификатору пользователя данного твита. В настоящее время у меня есть следующие два варианта:Ссылка на метод цепочки карт

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

Мне не нравится лямбда-выражение в первом варианте, не будучи вынужден назвать два 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'. Я принимаю «Nope» в качестве ответа. – 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().

Смежные вопросы