Kann ich in Java ein Prädikat erstellen, das einen Filter auf mehr als ein Objekt anwendet?


8

Ich habe ein Prädikat, mit dem ich eine Liste desselben Entitätsobjekts filtere:

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

Ich muss auch denselben Filter mit genau derselben Bedingung auf genau dasselbe Feld auf eine Liste von DTOs anwenden, bei denen das DTOS basierend auf der Entität von zuvor erstellt wird:

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

Ist es möglich, dies zu erreichen, ohne zwei verschiedene Prädikate zu instanziieren? Wenn möglich, möchte ich dies erreichen, indem ich nur eine mache Predicate.


5
Sind DWHDealDTOund DWHDealverwandt? (wie die Erweiterung derselben Klasse)
ernest_k

1
Gibt getCompany()in beiden Fällen der gleiche Typ zurück?
Ruslan

@ernest_k Nein, sie erweitern leider nicht die gleichen Klassen. Aber sie haben meistens die gleichen Felder.
LordGriffith

3
Und was ist mit der Definition einer gemeinsamen Schnittstelle? (dh von beiden Klassen implementiert)
Benoit

1
Die Regeln unterscheiden sich nicht von z. B. dem Implementieren der Predicatemit einer normalen Klasse oder dem Versuch, eine Methode zu schreiben, die beide DWHDealund DWHDealDTOals Parameter akzeptiert . Wenn diese Klassen keine gemeinsame Schnittstelle oder Oberklasse haben, die eine gemeinsame Methode deklariert, haben sie keine gemeinsame Methode, sondern nur zwei nicht verwandte Methoden, die zufällig denselben Namen haben.
Holger

Antworten:


5

Unter der Annahme , getCompany()kehrt ein StringSie schaffen könnten Predicate<String>:

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

Und dann verwenden Sie es wie:

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

Es gibt jedoch nicht viel Nutzen, da fast derselbe Code erforderlich ist.


Es hat einen Vorteil. Anstatt Prädikate für jedes DTO zu erstellen, reicht bei diesem Ansatz nur ein Prädikat für alle DTOs aus. Dies führt zu einer besseren Wiederverwendbarkeit des Codes. Weniger geschriebener Code bedeutet weniger zu verwaltenden Code.
Ketan R

1
@KetanR dies hat immer noch ein Prädikat für jedes DTO, um genau zu sein, dies hat sogar ein weiteres Prädikat.
Holger

0

Wenn nur Gleichheit geprüft wird, können Sie das statische Prädikat isEqual (Object targetRef) verwenden. Siehe Java-Dokument 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

Ich denke, Sie benötigen eine, Function<T,R>bevor Sie verwenden Predicate:

Es gibt zwei Konzepte für die Funktion. Erstens ist a, java.util.function.Functiondas ein Argument akzeptiert und ein Ergebnis erzeugt . Die zweite ist die Zwischenbetriebskennstrom, der jedes Element in einem wandelt Strom in einem anderen Objekt über das bereitgestellte Funktion.

In Ihrem Fall Functionsollte das so aussehen:

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

Ich habe das folgende Basisprogramm mit Erfolg ausprobiert:

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

Wie in den Kommentaren vorgeschlagen, wäre die gemeinsame Schnittstelle die bevorzugte Lösung.

Ich denke, Sie könnten so etwas tun, aber um fair zu sein, ist es hässlich.

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);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.