В Java можно ли создать предикат, который применяет фильтр к нескольким объектам? - PullRequest
8 голосов
/ 03 марта 2020

У меня есть предикат, который я использую для фильтрации списка того же объекта сущности:

Predicate<DWHDeal> companyFilter = i -> i.getCompany().equals(company);

Мне также нужно применить тот же фильтр с точно таким же условием к точно такому же полю, на список DTO, в которых DTOS построен на основе ранее существовавшего объекта:

Predicate<DWHDealDTO> companyFilterDTO = i -> i.getCompany().equals(company);

Возможно ли достичь этого без создания двух разных предикатов? Если возможно, я бы хотел добиться этого, сделав только один Predicate.

Ответы [ 4 ]

5 голосов
/ 03 марта 2020

Предполагая, что getCompany() возвращает String, вы можете создать Predicate<String>:

Predicate<String> predicate = s -> s.equals(company);

И затем использовать его следующим образом:

list.stream()
    .filter(dto -> predicate.test(dto.getCompany()))
    ...

Но не так много пользы, поскольку требуется почти такой же код.

0 голосов
/ 03 марта 2020

Если равенство проверяется только тогда, вы можете использовать stati c Predicate isEqual (Object targetRef). см. java do c https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#isEqual - java .lang.Object-

class StudentView{
    String name;

    public StudentView(String name) {
        this.name = name;
    }
}
class StudentDTO{
    String name;

    public StudentDTO(String name) {
        this.name = name;
    }
}

public void testPredicate(){
    StudentView studentView= new StudentView("John");
    StudentDTO studentDTO = new StudentDTO("Sam");
    Predicate p = Predicate.isEqual("John");
    System.out.println("Test for Student View "+ p.test(studentView.name));
    System.out.println("Test for Student DTO "+ p.test(studentDTO.name));


}
0 голосов
/ 03 марта 2020

Как предлагается в комментариях, общий интерфейс был бы предпочтительным решением.

Я думаю, вы могли бы сделать что-то подобное, но, честно говоря, это ужасно.

private String getCompany(Object o) {
    if(o instanceof DWHDeal)
        return ((DWHDeal) o).getCompany();
    else
        return ((DWHDealDTO) o).getCompany();
}

Predicate<Object> companyFilter = i -> getCompany(i).equals(company);
0 голосов
/ 03 марта 2020

Я думаю, вам понадобится Function<T,R> перед использованием Predicate:

Есть две концепции для функции. Первый - это java.util.function.Function, который принимает один аргумент и выдает результат . Вторая - это карта промежуточных операций потока, которая преобразует каждый элемент в stream в другой объект с помощью предоставленной функции.

В вашем случае Function должен выглядеть следующим образом :

Function<DWHDeal, DWHDealDTO> myFunction = new Function<DWHDeal, DWHDealDTO>() {
  public DWHDealDTO apply(DWHDeal t) {
    return ... ;
  }
};

Я попробовал основную программу c, как показано ниже:

static class DWHDeal{
    String name;

    public DWHDeal(String name) {
      this.name = name;
    }
  }
  static class DWHDealDTO{
    String name;

    public DWHDealDTO(String name) {
      this.name = name;
    }
  }

  static Predicate<DWHDealDTO> companyFilter = i -> i.name.equalsIgnoreCase("com");
  public static void main(String[] args) {
    Function<DWHDeal, DWHDealDTO> myFunction = new Function<DWHDeal, DWHDealDTO>() {
      public DWHDealDTO apply(DWHDeal t) {
        return new DWHDealDTO("com");
      }
    };
    DWHDeal newDWHDealDTOObj = new DWHDeal("com");
    System.out.println(companyFilter.test(myFunction.apply(newDWHDealDTOObj)));  //Works
  }
...