2017-11-05 5 views
2

Ich habe zwei Sätze von Rollen. Einer aus einer Datenbank, ein anderer aus der Benutzeroberfläche. Ich habe auch eine Vergleichsmethode für zwei Rollen basierend auf dem Namen der Rolle geschrieben.Java-8 filtert zwei Sätze mit Lambdas

Problem: Ich möchte Rolle extrahieren (eine aus der Datenbank behalten), wenn der Vergleichswert mit lambdas expression den Wert true zurückgibt.

Die matchingRoleNames funktionieren gut, aber ich suche die besten lambdas Praktiken, die ohne for-Schleife zu tun. Das ist mein Set Ergebnis ist die fein gearbeitet:

Set<Role> rolesFromUI = user.getRolesFromUI(); 
Stream <Role> roleStreamFromDB = roleService.getAllRolesStreamFromDatabase(); 

Set<Role> matchingRoleNames = roleStreamFromDB.filter(role-> 
     { 
      for(Role roleTmp:rolesFromUI){ 
       if(roleTmp.compareTo(role)==0){ 
        return true; 
       } 
      } 
      return false; 
     }) 

public int compareTo(Role role){ 
     return this.roleName.compareTo(role.getRoleName());  
} 

Danke

+3

Siehe https://stackoverflow.com/help/someone -answers – c0der

Antwort

1

stattdessen die für jede Schleife innerhalb des filter Zwischen Betrieb des ersten Stroms zu verwenden, können Sie nur den anderen Satz streamen und sehen wenn eines der Elemente mit einem Element des ersten Streams übereinstimmt.

dh:

Set<Role> matchingRoleNames = roleStreamFromDB.filter(e -> rolesFromUI.stream().anyMatch(x -> x.compareTo(e) == 0)) 
               .collect(Collectors.toSet()); 
+0

Das funktioniert gut. Danke M Aominè! –

+0

Können wir Collectors.toCollection (HashSet :: new) hinzufügen, um DB-Rollen zu filtern? Was ist der Nutzen? –

1

Wie Sie sagen, dass Sie Rollen nach dem Namen vergleichen möchten, können Sie tun, was Sie wollen, indem man zuerst an einen Set die Namen der UI Rollen zu sammeln und dann, wenn die Filterung DB Rollen, nur prüfen, ob der Name der aktuellen Rolle in dem Satz:

// Collect UI role names 
Set<String> uiRoleNames = user.getRolesFromUI().stream() 
    .map(Role::getRoleName) 
    .collect(Collectors.toSet()); 

// Filter DB roles 
Set<Role> filteredRoles = roleService.getAllRolesStreamFromDatabase() 
    .filter(role -> uiRoleNames.contains(role.getRoleName())) 
    .collect(Collectors.toSet()); 

diese einfach und effizient ist, weil der zurück Set von Collectors.toSet() erwartet wird, für Lookups effizient zu sein (dies bedeutet, dass seine contains Methode wird O(1) für den durchschnittlichen Fall sein).

Wenn Sie 100% sicher sein wollen, dass der zurück Satz O(1) für contains sein wird, könnten Sie die UI-Rollennamen sammeln wie folgt:

Set<String> uiRoleNames = user.getRolesFromUI().stream() 
    .map(Role::getRoleName) 
    .collect(Collectors.toCollection(HashSet::new)); 
+0

Hallo Herr Schaffner, was meinst du mit O (1)? –

+0

@BertGuim Hallo, Entschuldigung, ich habe es nicht erklärt. "O (1)" bedeutet, dass die Methode in konstanter Zeit abläuft, d. H. Es dauert immer dieselbe Zeit auszuführen, unabhängig davon, ob die Menge 10 Elemente oder 20 Millionen Elemente enthält. –

+0

Verstanden, sehr interessant. –