Em Java, posso criar um predicado que aplique um filtro em mais de um objeto?


8

Eu tenho um predicado que eu uso para filtrar uma lista do mesmo objeto de entidade:

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

Também preciso aplicar o mesmo filtro, com a mesma condição exata no mesmo campo, em uma lista de DTOs em que o DTOS é criado com base na entidade anterior:

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

É possível conseguir isso sem instanciar dois predicados diferentes? Se possível, eu gostaria de conseguir isso fazendo apenas um Predicate.


5
São DWHDealDTOe DWHDealrelacionados? (como estender a mesma classe)
ernest_k 03/03

1
Retorna getCompany()o mesmo tipo nos dois casos?
Ruslan

@ernest_k Não, eles não estendem as mesmas classes, infelizmente. Mas eles têm principalmente os mesmos campos.
LordGriffith

3
E quanto a definir uma interface comum? (ou seja, implementado pelas duas classes)
Benoit

1
As regras não são diferentes, por exemplo, implementar o Predicatecom uma classe comum ou tentar escrever um método que aceite ambos DWHDeale DWHDealDTO, como parâmetro. Se essas classes não tiverem interface ou superclasse comum declarando um método comum, elas não terão um método comum, apenas dois métodos não relacionados que tenham o mesmo nome.
Holger

Respostas:


5

Supondo getCompany()retornos a, Stringvocê pode criar Predicate<String>:

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

E depois usá-lo como:

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

Mas não há muitos benefícios, pois requer quase o mesmo código.


Tem um benefício. Em vez de criar Predicados para cada DTO, apenas um Predicado é suficiente com essa abordagem para todos os DTOs. Portanto, isso leva a uma melhor reutilização do código. Menos código escrito significa menos código para gerenciar.
Ketan R

1
@KetanR, isso ainda tem um predicado para cada DTO, para ser mais preciso, esse ainda tem mais um predicado.
Holger

0

Se a igualdade for apenas verificar, você poderá usar o Predicate isEqual estático (Object targetRef). consulte java doc 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

Eu acho que você precisará de um Function<T,R>antes de usar Predicate:

Existem dois conceitos para Function. Primeiro é um java.util.function.Functionque aceita um argumento e produz um resultado . O segundo é o mapa de operação intermediária do fluxo, que converte cada elemento em um fluxo em outro objeto por meio da função fornecida.

No seu caso, Functiondeve parecer com:

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

Eu tentei o programa básico como abaixo com sucesso:

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
  }

0

Conforme sugerido nos comentários, a interface comum seria a solução preferida.

Eu acho que você poderia fazer algo assim, mas para ser justo, é feio.

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);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.