如何在使用方法引用的同时在filter()中链接谓词 ?

问题描述 投票:0回答:1

我有一个像这样的电影:

        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());
        }

}

如何在使用方法引用时链接谓词过滤器?我知道方法引用可以看作是lambda仅调用特定方法的简写。在我正在阅读的书中,它说:“ ...方法引用使您可以从现有方法实现中创建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。在我们大学的课程中,没有提到流。所以我决定我自己开始。新手。

java lambda filter java-stream predicate
1个回答
1
投票

您不能这样做,因为这:

Movie::titleFilter(titleFilter)

并不是真正的方法参考。您有点传入参数,这似乎表明您要call方法。但是您正在使用::,这使其看起来像方法引用。

但是,如果您只是执行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中不存在方法的“部分应用程序”之类的东西。 (如果它存在,那将是很酷的...)

© www.soinside.com 2019 - 2024. All rights reserved.