En Java, ¿puedo hacer un predicado que aplique un filtro en más de un objeto?

8

Tengo un predicado que uso para filtrar una lista del mismo Objeto de entidad:

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

También tengo que aplicar el mismo filtro, con exactamente la misma condición en el mismo campo, en una lista de DTO donde se construye el DTOS basado en la entidad de antes:

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

¿Es posible lograr esto sin instaurar dos predicados diferentes? Si es posible, me gustaría lograr esto haciendo solo uno Predicate.

Lord Griffith
fuente
55
Son DWHDealDTOy DWHDealrelacionados? (como extender la misma clase)
ernest_k
1
¿ getCompany()Devuelve el mismo tipo en ambos casos?
Ruslan
@ernest_k No, desafortunadamente no extienden las mismas clases. Pero tienen en su mayoría los mismos campos.
Lord Griffith
3
¿Y qué hay de definir una interfaz común? (es decir, implementado por ambas clases)
Benoit
1
Las reglas no son diferentes a, por ejemplo, implementarlas Predicatecon una clase ordinaria o tratar de escribir un método que acepte ambas DWHDealy DWHDealDTO, como parámetro. Si estas clases no tienen una interfaz común o una superclase que declare un método común, no tienen un método común, solo dos métodos no relacionados que tienen el mismo nombre.
Holger

Respuestas:

5

Suponiendo que getCompany()devuelve un Stringque podría crear Predicate<String>:

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

Y luego usándolo como:

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

Pero no hay muchos beneficios ya que requiere casi el mismo código.

Ruslan
fuente
Tiene un beneficio. En lugar de crear predicados para cada DTO, solo un predicado es suficiente con este enfoque para todos los DTO. Entonces esto conduce a una mejor reutilización del código. Menos código escrito significa menos código para administrar.
Ketan R
1
@KetanR esto todavía tiene un predicado para cada DTO, para ser precisos, esto tiene incluso un predicado más.
Holger
0

Si la igualdad es solo verificar, entonces puede usar Predicate estático isEqual (Object targetRef). ver 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));


}
ankur agnihotri
fuente
0

Creo que necesitará un Function<T,R>antes de usar Predicate:

Hay dos conceptos para la función. Primero es un java.util.function.Functionque acepta un argumento y produce un resultado . El segundo es el mapa de operación intermedia de flujo que convierte cada elemento en un flujo en otro objeto a través de la función suministrada.

En su caso, Functiondebería verse así:

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

Probé el programa básico de la siguiente manera con éxito:

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
  }
Vishwa Ratna
fuente
0

Como se sugiere en los comentarios, la interfaz común sería la solución preferida.

Supongo que podrías hacer algo como esto, pero para ser justos, es feo.

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);
Bentaye
fuente