Wie filterst du geschachtelte Schleifen mit Java 8 streams und Filter?
Wie filterst du geschachtelte Schleifen mit java8-streams und Filter?
Angenommen ich habe eine Liste mit Autos (List<Car>
), jedes Auto mit einer Liste der Motoren (List<Engine>
), jeden Motor mit einem List<Parts>
.
In regulären Java-dieser Struktur kann beschrieben werden als:
for(Car car : cars) {
for (Engine engine : car.getEngines()) {
for (Part part : engine.getParts()) {
//...
}
}
}
Nehme an, dass ich Sie initialisieren die Liste der Autos:
List<Car> cars = new ArrayList<Car>(Arrays.asList(new Car(), new Car(), new Car()));
cars.get(0).setEngines(null);
cars.get(1).setEngines(new ArrayList<Engine>());
cars.get(2).setEngines(new ArrayList<Engine>() {{
add(new Engine());
add(null);
add(new Engine());
}});
Wenn ich will, um null-Werte herausfiltern von List<Engine>
würde, dann würde ich das tun
cars.stream().filter(p -> p.getEngines() != null).forEach(System.out::println);
Wenn ich will, um filter leer aus arraylists der Liste, dann würde ich das tun
cars.stream().filter(p -> !p.getEngines().isEmpty()).forEach(System.out::println);
Aber wie Entferne ich die null - Engine
im 3. Auto und noch zwei andere Motoren, befestigt, um die ursprüngliche Verzeichnis-Struktur? In anderen Worten, können wir gehen in die 2., 3., N-TEN Stufe der Hierarchie mit Java-8-Filter oder tun die Filter funktionieren nur auf der obersten Ebene? Ich habe auch versucht zu verwenden .anyMatch()
ohne viel Glück.
nur weiter zu verdeutlichen, betrachten wir das folgende Beispiel:
Ich habe 3 Autos in meiner garage. Jedes Auto hat 3 Platzhalter für den Motor. Jeder Motor hat 3 Platzhalter für die Teile, aus denen sich der Motor:
Car #1:
Engine#1: part1, part2, part3
Engine#2: null, part2, empty
Engine#3: part1, null, part3
Car #2:
Engine#1: part1, part2, part3
empty: null, null, null
null: null, null, null
Car #3:
Engine#1: null, empty, part3
Engine#2: null, part2, empty
Engine#3: part1, null, part3
Frage: wie verwenden wir Java 8 .filter, so dass, wenn nach dem filtern bekomme ich die folgende:
Car #1:
Engine#1: part1, part2, part3
Engine#2: part2,
Engine#3: part1, part3
Car #2:
Engine#1: part1, part2, part3
Car #1:
Engine#1: part3
Engine#2: part2,
Engine#3: part1,part3
=======================
Ein weiteres Beispiel
Jungs, ich hoffe, daß dieses Beispiel, das ich gerade gemacht, bis klarer ist:.. im Wesentlichen ist es die gleiche wie oben, nur es ist Ausführlicher und statt Autos, die wir denken können, die Banken zu minimieren Abstraktion. Für die übersichtlichkeit habe ich alle Felder der öffentlichkeit, ich hoffe, Sie nicht mind.
Angenommen, ich bin verbunden mit 4 Banken in meiner 'bank Geldbeutel"
Bank#1:
Ich körperlich bank hier. Ich bin gezwungen zu haben 3 Konten, aber nur 2 gefüllt mit etwas Geld und 3. ist noch offen (dh null)
Bank #2:
Ich Plane, die bank hier. Account-support-Struktur wird erstellt (leere ArrayList), aber keine Konten Hinzugefügt werden
Bank #3:
Ich füllte einige marketing-form. Sie haben mich in Ihrem CRM, aber keine Konten jemals geöffnet werden
Bank #4:
Diese bank abgebrannt, es ist ein Artefakt Platzhalter in der Brieftasche, die null ist.
Folgende code beschreibt diese:
public class Bank_Wallet {
public static void main(String[] args) {
List<Bank> banks = new ArrayList<Bank>(Arrays.asList(new Bank(), new Bank(), new Bank(), null));
//1st bank with physical accounts, but one of them is null
banks.get(0).accounts = Arrays.asList(new Account(), null, new Account());
//2nd bank with empty accounts
banks.get(1).accounts = new ArrayList<Account>();
System.out.println("RAW original");
banks.stream().forEach(System.out::println);
System.out.println("\nFiltered result... ");
banks.stream()//get stream
.filter(p -> p != null) //get rid of null banks
.filter(p -> p.accounts != null) //get rid of null accounts
.filter(p -> !p.accounts.isEmpty()) //get rid of empty accounts
//.filter(p->p.accounts. ?????? ??) ?? how do I remove null account from the remaining bank entry?
.forEach(System.out::println);
}//main
}
Die Rennklassen sind hier:
public class Bank {
public String name;
public static int counter = 0;
public List<Account> accounts;
public Bank() {
this.name = "Bank: #" + Bank.counter++;
}
@Override
public String toString() {
return "Bank [name=" + this.name + ", accounts=" + this.accounts + "]";
}
public class Account {
public String name;
public static int counter;
public Account() {
this.name = "Account: " + Account.counter++;
}
@Override
public String toString() {
return "Account [name=" + this.name + "]";
}
}
wenn Sie diesen code ausführen, werden Sie sehen, dass nach der vorgeschlagenen filtern alle, ich bin mit der linken, ist
Bank [name=Bank: #0, accounts=[Account [name=Account: 0], null, Account [name=Account: 1]]]
Frage:
Was die anderen filter muss ich tun, fügen Sie den code ein, um das obige Ergebnis nicht zeigen null-im-Konten und haben doch die Allgemeine Struktur (Bank->Konto>usw.>etc)
Bank [name=Bank: #0, accounts=[Account [name=Account: 0], Account [name=Account: 1]]]
- führen Sie anzeigen über jeden Eintrag der äußeren Liste. Die Karte sollte die Funktion filtern Sie heraus, was Sie nicht wollen.
- Könnten Sie etwas konkreter in dem, was Sie zu erreichen versuchen, mit Ihren Schleifen ? Ich denke, Andreas hob ein guter Punkt, zeigt mir, dass ich zu viele Annahmen über das, was du suchst, denn deine Frage ist nicht spezifisch genug. Geben Sie uns nur ein Beispiel für die Eingabe zusammen mit der gewünschten Ausgabe
- So, das Sie drucken möchten, das ganze Auto unter Ausschluss jeglicher null/leer-Komponenten?
- Ist, dass etwas angezeigt werden oder so etwas erhoben werden ?
- ja das ganze Auto Struktur (Liste) mit null-Werte/Leergut herausgefiltert in verschiedene Tiefe Ebenen, die mit java 8 filter
- Wenn Sie sich auf
Car.toString()
gibt es nichts, was Sie tun können, mit Bächen oder sogar Schleifen heraus zu filtern, sub-Komponenten. Sie haben entweder implementierentoString()
anders, oder drucken Sie Komponenten iterativ. - es kann gesammelt werden, wie auch angezeigt. Gesammelt wird viel bevorzugt.
- ja, dass ist das, was ich derzeit habe: ich habe 3 for-Schleifen und bekommen es heraus gefiltert, die Art und Weise, aber obwohl java 8 filter vielleicht schon eine bessere Lösung
- das sammeln dieser würde entweder mutieren die Autos oder neue zu erstellen, welche wird erwartet ?
- Wussten Sie, dass, nutzen Sie einfach das Ergebnis der
Arrays.asList
überall dort, wo einList
ist erforderlich, D. H., dass Sie nicht überladen Sie Ihren code mit gazillion verschiedene versuche anlegen und füllenArrayList
s? - Die "Klarstellung" ist eher verwirrend. Was bedeutet es, wenn ein "Teil" ist mit der Bezeichnung "leer" und wie "leer" oder sogar
null
Listen enthält dreinull
Elemente? - Jungs, gebt mir ein paar Stunden - ich komme wieder mit einem Beispiel mit Ausführlicher Erklärung des Problems. Sorry für die Verwirrung...
- Hast du auch dieses problem lösen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den stream-äquivalent von
ist
Den
...
- code wird jedoch nicht der Zugang zucar
undengine
.Überprüfung auf null, können Sie in zwei Orten:
oder
flatMap
hier nicht verwendet werden können, oder nicht auf diese Weise. Wir wollen nicht verlieren, der Verweis auf das Auto. Auch, alle Ihre snippets werfen kann einNullPointerException
... Und warum tun Sie nicht einfach schreiben das ?
getEngines()
zurückList<Engine>
(oder ähnlich), die nichtgetParts
.System.out::println
aufgerufen werden, einmal für jedeCar
, das ist sehr einem anderen Ergebnis als diefor
Schleife code, der ausgeführt wird...
für jedenPart
."levels"
, nicht als tatsächlichen code. Wenn es tatsächliche code, dann hast du absolut Recht, aber es würde merkwürdig klingen drucken Sie die Autos mehrmalsWie etwa die folgenden?
Produziert folgende :
Auto C0
Auto C1
Auto-C2 Motor C2E1 Teil DefaultPart Motor C2E2 Teil DefaultPart
Haben überschriebenen "toString" für Auto - /Motor - /Teil-Klassen.
Hoffe, das hilft.
können Sie
removeIf()
wie folgt: