编写对特定类型的任意对象的实例方法的引用

时间:2018-02-19 03:00:27

标签: lambda compiler-errors java-8 method-reference

编译没有错误:

Function<T, List<R>> f = T::getRs;
Function<List<R>, Stream<R>> g = List::stream;
Function<T, Stream<R>> h = f.andThen(g);
List<T> ts = ...;
ts.stream().flatMap(h);

但这会产生错误:

List<T> ts = ...;
ts.stream().flatMap(T::getRs.andThen(List::stream));

错误是:

error: method reference not expected here
        .flatMap(T::getRs.andThen((List::stream)))
                 ^
error: invalid method reference
        .flatMap(T::getRs.andThen((List::stream)))
                                   ^
  non-static method stream() cannot be referenced from a static context
  where E is a type-variable:
    E extends Object declared in interface Collection

我原以为这两种方法是等价的。我错过了一些语法吗?有些人可能在某个地方分组?我宁愿选择后者&#34; one-line&#34;如果可能的话。

2 个答案:

答案 0 :(得分:2)

这不是方法引用的正确语法;好像你试图打电话给这样的东西(请注意括号,即使它仍然不正确):

List<T> ts = ...;

ts.stream().flatMap((T::getRs).andThen(List::stream));

要将其分成一行,您可以将其拆分为对Stream#map然后Stream#flatMap的调用:

List<T> ts = ...;

ts.stream().map(T::getRs).flatMap(List::stream);

答案 1 :(得分:2)

您的单行解决方案的问题是,编译器需要一个目标类型来调用andThen。如果您将第一个方法引用转换为Function,它就可以正常工作:

ts.stream().flatMap(((Function<T, List<R>>) T::getRs).andThen(List::stream));

首选方法是将这两个分成mapflatMap或使用lambda表达式,因为它更具可读性。