2014-11-14 190 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()调用。