Java 使用方法引用替换链式方法调用
“Java8Lambdas:Practical Functional Programming”有一个例子,说明如何在Java 使用方法引用替换链式方法调用,java,lambda,java-8,Java,Lambda,Java 8,“Java8Lambdas:Practical Functional Programming”有一个例子,说明如何在StreamAPI中使用peek方法。这段代码打印出名称以“The”开头的艺术家国籍: Set nations=album.getMusiner() .filter(artist->artist.getName().startsWith(“The”)) .map(艺术家->艺术家.getNational()) .peek(国家->系统输出.println(国家)) .collect
Stream
API中使用peek
方法。这段代码打印出名称以“The”开头的艺术家国籍:
Set nations=album.getMusiner()
.filter(artist->artist.getName().startsWith(“The”))
.map(艺术家->艺术家.getNational())
.peek(国家->系统输出.println(国家))
.collect(Collectors.toList());
我想用方法引用重写此代码:
Set<Nationality> nationalities = album.getMusician()
.filter(artist -> artist.getName().startsWith("The"))
.map(Artist::getNationality)
.peek(System.out::println)
.collect(Collectors.toList());
Set nations=album.getMusiner()
.filter(artist->artist.getName().startsWith(“The”))
.map(艺术家::GetNational)
.peek(System.out::println)
.collect(Collectors.toList());
是否有任何重写
过滤器(artist->artist.getName().startsWith(“The”))
的解决方案?无法用方法引用替换该行
方法引用的工作原理是,在整个lambda表达式中只使用一个对象,编译器可以使用目标类型推断它(引用不重要,类型可以推断) 所以 被替换为
Artist::getNationality
这里的Artist::getNational
方法与目标类型匹配,而不需要任何进一步的信息
对于
artist->artist.getName().startsWith(“The”)
,lambda表达式中有两个方法调用。顺序、参数很重要,必须指定
看起来好像应该推断artist
引用,但是编译器不知道应该调用startsWith(“the”)
方法的哪个对象
希望这有帮助。您需要创建一个单独的方法,该方法接受艺术家并返回布尔值:
private boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(this::nameStartsWithThe)
private boolean nameStartsWithThe(艺术家a){
返回a.getName().startsWith(“The”);
}
Set nations=album.getMusiner()
.filter(this::nameStartsWithThe)
或使用静态方法:
private static boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(MyClass::nameStartsWithThe)
私有静态布尔名称开始(艺术家a){
返回a.getName().startsWith(“The”);
}
Set nations=album.getMusiner()
.filter(MyClass::nameStartsWithThe)
您需要一些东西来组合这两种方法。有一些方法可用于组合方法(IntUnaryOperator
具有compose
和,然后
方法可将两个IntUnaryOperator
组合成一个新的IntUnaryOperator
)。但我发现的那些似乎都专门用于某些类型的功能接口;为每一对可能的函数接口类型定义compose
方法太难了
我确实做了一些工作,将组成一个函数
和一个谓词
,以获得一个新的谓词
:
static <T,U> Predicate<T> functionPredicate(Function<T,U> func, Predicate<U> pred) {
return obj -> pred.test(func.apply(obj));
}
其中,this类
是包含的任何类,从
开始。这很有效。如果您想避免编写新方法(如startsWithThe
),您可能可以编写一个“参数化谓词”泛型方法,这样您就可以编写
Predicate<Artist> pred = functionPredicate(Artist::getName, parameterizedPredicate(String::startsWith, "The"));
Predicate pred=functionPredicate(Artist::getName,parameteredPredicate(String::startsWith,“The”);
但我还没试过
因此,似乎有可能想出一些方法,让您使用方法引用而不是lambda。我怀疑这是否值得。对我来说,方法引用只是某些lambda的简写;除非你能用一个简单的方法引用做你想做的事情,否则我认为使用lambda足够简洁明了,你不需要像我的functionPredicate
方法那样添加所有额外的繁琐。我看到过一些问题,比如“我如何使用方法引用来代替lambda?”,我真的不明白为什么
static <T,U> Predicate<T> functionPredicate(Function<T,U> func, Predicate<U> pred) {
return obj -> pred.test(func.apply(obj));
}
static boolean startsWithThe(String s) {
return s.startsWith("The");
}
Predicate<Artist> pred = functionPredicate(Artist::getName, ThisClass::startsWithThe);
Predicate<Artist> pred = functionPredicate(Artist::getName, parameterizedPredicate(String::startsWith, "The"));