如何在使用方法引用时在 filter() 中链接 Predicate<T>?
How to chain Predicate<T> in filter() while using method references?
我有一个 class 电影是这样的:
public class Movie {
private int id, duration, publishingYear;
private String title, translation;
public Movie(int id, int duration, int publishingYear, String title, String translation) {
super();
this.id = id;
this.duration = duration;
this.publishingYear = publishingYear;
this.title = title;
this.translation = translation;
}
public Predicate<Movie> titleFilter(String filter){
return m -> m.getTitle().toLowerCase().contains(filter.toLowerCase());
}
public Predicate<Movie> translationFilter(String filter){
return m -> m.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
}
如何在使用方法引用时链接 Predicate 过滤器?我知道对于只调用特定方法的 lambda,方法引用可以被视为 shorthand。在我正在阅读的书中,它说:“......方法参考让你从现有的方法实现中创建一个 lambda 表达式......”。那么,为什么我不能这样做?
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter((Movie::titleFilter(titleFilter)).or(Movie::translationFilter(translationFilter)))
.collect(Collectors.toList());
我知道这会起作用:
Predicate<Movie> titlePredicate = ( m -> m.getTitle().toLowerCase().contains(titleFilter));
Predicate<Movie> translationPredicate = ( m -> m.getTitle().toLowerCase().contains(translationFilter));
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter(titlePredicate.or(translationPredicate))
.collect(Collectors.toList());
还有这个(只需插入 filter() ):
public boolean tFilter(String filter){
return this.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
我最近开始使用 lambda 和 Stream API。在我们大学的课程中,没有提到流。所以我重新开始我自己。新手.
你不能那样做,因为:
Movie::titleFilter(titleFilter)
并不是真正的方法参考。你是在传递一个参数,这似乎表明你想调用这个方法。但是您正在使用 ::
,这使它看起来像一个方法引用。
但是,如果您只是 Movie::titleFilter
,那将是一个方法引用,但不能转换为 Predicate<Movie>
。如果您明确指定了类型,它可以转换为 Function<String, Predicate<Movie>>
,但这显然不是您想要的。
另请注意,即使您在 Movie
中有两个像这样的方法(它们都可以转换为 Predicate<Movie>
):
public boolean predicate1() { ... }
public boolean predicate2() { ... }
你不能or
他们这样:
Movie::predicate1.or(Movie::predicate2)
因为 Movie::predicate1
本身没有类型。这是为了允许它转换为具有兼容签名的任何功能接口。你必须做:
((Predicate<Movie>)Movie::predicate1).or(Movie::predicate2)
相反。
我认为你的意图是:
// note the static modifiers
public static Predicate<Movie> titleFilter(String filter){
return m -> m.getTitle().toLowerCase().contains(filter.toLowerCase());
}
public static Predicate<Movie> translationFilter(String filter){
return m -> m.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
并且:
// note that I am calling the methods which *return* a Predicate<Movie>
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter((Movie.titleFilter(titleFilter)).or(Movie.translationFilter(translationFilter)))
.collect(Collectors.toList());
基本上,方法引用是不能传参的,Java中没有方法"partial application"。 (不过要是有就好了...)
我有一个 class 电影是这样的:
public class Movie {
private int id, duration, publishingYear;
private String title, translation;
public Movie(int id, int duration, int publishingYear, String title, String translation) {
super();
this.id = id;
this.duration = duration;
this.publishingYear = publishingYear;
this.title = title;
this.translation = translation;
}
public Predicate<Movie> titleFilter(String filter){
return m -> m.getTitle().toLowerCase().contains(filter.toLowerCase());
}
public Predicate<Movie> translationFilter(String filter){
return m -> m.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
}
如何在使用方法引用时链接 Predicate 过滤器?我知道对于只调用特定方法的 lambda,方法引用可以被视为 shorthand。在我正在阅读的书中,它说:“......方法参考让你从现有的方法实现中创建一个 lambda 表达式......”。那么,为什么我不能这样做?
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter((Movie::titleFilter(titleFilter)).or(Movie::translationFilter(translationFilter)))
.collect(Collectors.toList());
我知道这会起作用:
Predicate<Movie> titlePredicate = ( m -> m.getTitle().toLowerCase().contains(titleFilter));
Predicate<Movie> translationPredicate = ( m -> m.getTitle().toLowerCase().contains(translationFilter));
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter(titlePredicate.or(translationPredicate))
.collect(Collectors.toList());
还有这个(只需插入 filter() ):
public boolean tFilter(String filter){
return this.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
我最近开始使用 lambda 和 Stream API。在我们大学的课程中,没有提到流。所以我重新开始我自己。新手.
你不能那样做,因为:
Movie::titleFilter(titleFilter)
并不是真正的方法参考。你是在传递一个参数,这似乎表明你想调用这个方法。但是您正在使用 ::
,这使它看起来像一个方法引用。
但是,如果您只是 Movie::titleFilter
,那将是一个方法引用,但不能转换为 Predicate<Movie>
。如果您明确指定了类型,它可以转换为 Function<String, Predicate<Movie>>
,但这显然不是您想要的。
另请注意,即使您在 Movie
中有两个像这样的方法(它们都可以转换为 Predicate<Movie>
):
public boolean predicate1() { ... }
public boolean predicate2() { ... }
你不能or
他们这样:
Movie::predicate1.or(Movie::predicate2)
因为 Movie::predicate1
本身没有类型。这是为了允许它转换为具有兼容签名的任何功能接口。你必须做:
((Predicate<Movie>)Movie::predicate1).or(Movie::predicate2)
相反。
我认为你的意图是:
// note the static modifiers
public static Predicate<Movie> titleFilter(String filter){
return m -> m.getTitle().toLowerCase().contains(filter.toLowerCase());
}
public static Predicate<Movie> translationFilter(String filter){
return m -> m.getTranslation().toLowerCase().contains(filter.toLowerCase());
}
并且:
// note that I am calling the methods which *return* a Predicate<Movie>
ArrayList<Movie> filteredMovies = (ArrayList<Movie>) app.getMovies().stream()
.filter((Movie.titleFilter(titleFilter)).or(Movie.translationFilter(translationFilter)))
.collect(Collectors.toList());
基本上,方法引用是不能传参的,Java中没有方法"partial application"。 (不过要是有就好了...)