Angenommen, eine Klasse MyClass
:Stream: auf Kinder filtern, gibt die Eltern
public class MyClass {
private final Integer myId;
private final String myCSVListOfThings;
public MyClass(Integer myId, String myCSVListOfThings) {
this.myId = myId;
this.myCSVListOfThings = myCSVListOfThings;
}
// Getters, Setters, etc
}
Und diesen Stream:
final Stream<MyClass> streamOfObjects = Stream.of(
new MyClass(1, "thing1;thing2;thing3"),
new MyClass(2, "thing2;thing3;thing4"),
new MyClass(3, "thingX;thingY;thingZ"));
Ich mag jede Instanz MyClass
zurückzukehren, die einen Eintrag "thing2"
in myCSVListOfThings
enthalten .
Wenn ich wollte ein List<String>
myCSVListOfThings
mit diesem leicht getan werden könnte:
List<String> filteredThings = streamOfObjects
.flatMap(o -> Arrays.stream(o.getMyCSVListOfThings().split(";")))
.filter("thing2"::equals)
.collect(Collectors.toList());
Aber was ich wirklich brauchen, ist ein List<MyClass>
.
Das ist, was ich jetzt haben:
List<MyClass> filteredClasses = streamOfObjects.filter(o -> {
Stream<String> things = Arrays.stream(o.getMyCSVListOfThings().split(";"));
return things.anyMatch(s -> s.equals("thing2"));
}).collect(Collectors.toList());
Aber irgendwie funktioniert es nicht richtig an. Jede sauberere Lösung als das Öffnen einer neuen Stream
innerhalb einer Predicate
?
Sieht sauberer aus. Am Ende wird "containsThing" in meinem Fall wahrscheinlich immer noch etwas wie der Code in der Frage sein, aber zumindest wird die Trennung von Bedenken erzwungen. Wie auch immer, sind Sie sich einer generischen Technik bewusst, um diese Art von Szenario zu vereinfachen? Angenommen, ich habe einen 'Stream' von' MyClass1', der eine Liste von 'MyClass2' enthält, die eine Liste von' MyClass3' enthält, die eine 'String' mit Dingen enthält. Wenn ich basierend auf dem String der Dinge filtern und eine 'List' zurückgeben wollte, wie würdest du es tun? –
In der Tat. Ihre ursprüngliche Lösung ist zu eng gekoppelt. Das Hinzufügen einer Inspektions-Methode ('contains()') entkoppelt die Oberfläche (äußere Erscheinung) von den inneren Details der 'MyClass'. –
Es ist besser, 'filter (o -> o.containsThing (" thing2 "))' zu 'filter (o -> o.containsThing ("; thing2; "))' 'zu ändern. – walsh