Ich habe noch keine Lösung gefunden, um eine Sammlung eines Typs (z. B. MyData
) mithilfe von Java-Streams auf ein Objekt eines anderen Typs (z. B. MyResult
) zu reduzieren.
@Test
public void streams() {
List<MyData> collection = Arrays.asList(
new MyData("1", "cool"),
new MyData("2", "green"),
new MyData("3", "night"));
// How reduce the collection with streams?
MyResult result = new MyResult();
collection.stream().forEach((e) -> {
if (e.key.equals("2")) {
result.color = e.value;
}
});
MyResult expectedResult = new MyResult();
expectedResult.color = "green";
assertThat(result).isEqualTo(expectedResult);
}
public static class MyData {
public String key;
public String value;
public MyData(String key, String value) {
this.key = key;
this.value = value;
}
}
public static class MyResult {
public String color;
public String material;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MyResult myResult = (MyResult) o;
return Objects.equals(this.color, myResult.color) &&
Objects.equals(this.material, myResult.material);
}
@Override
public int hashCode() {
return Objects.hash(this.color, this.material);
}
}
Gibt es eine Lösung mit einer Art Reduzieren oder Falten?
5 Antworten
Meintest du :
collection.stream()
.filter(e -> e.key.equals("2"))
.findFirst()
.orElse(null);//Or any default value
Sie können sogar eine Ausnahme auslösen:
collection.stream()
.filter(e -> e.key.equals("2"))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No data found"));
Versuchen Sie, eine Liste eines Typs basierend auf einer Bedingung in eine andere zu konvertieren?
MyResult result = new MyResult();
List<MyResult> resultList = collection.stream().filter(e -> e.key.equals("2")).map(e -> {
MyResult resultTemp = new MyResult();
result.color = e.value;
return result;
}).collect(Collectors.toList());
Versuche dies
Nun, Sie können zuerst das Element finden, nach dem Sie suchen
Optional<MyData> found = stream.filter(data -> data.key == 2).findFirst();
Ordnen Sie es dann Ihrem Ergebnis zu
Optional<MyResult> result = found.map(data -> {
MyResult r = new MyResult();
r.color = data.color;
return r;
});
Jetzt haben Sie ein Optional
, das leer ist, wenn der ursprüngliche Stream kein Element mit Schlüssel 2 enthielt, und ansonsten ein passendes MyResult
.
Die gesuchte Operation ist Map. Lesen Sie die Stream-Dokumente, um weitere Informationen zu erhalten: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Hier ist ein Codefragment zum Zuordnen Ihrer Liste von MyData-Objekten zu einer Liste von MyResult-Objekten.
List<MyResult> collect = collection.stream().map(myData -> {
MyResult myResult = new MyResult();
myResult.color = myData.value;
return myResult;
}).collect(Collectors.toList());
Wenn Sie nur einen einzelnen Wert suchen möchten, fügen Sie einfach vor der Map-Umwandlung eine Filtertransformation hinzu.
List<MyResult> collect = collection.stream()
.filter(myData -> "2".equals(myData.key))
.map(myData -> {
MyResult myResult = new MyResult();
myResult.color = myData.value;
return myResult;
}).collect(Collectors.toList());
Ich habe eine Lösung mit Collector.of()
gefunden.
Collector<MyData, MyResult, MyResult> myCollector = Collector.of(
() -> new MyResult(),
(a, e) -> {
if (e.key.equals("2")) {
a.color = e.value;
}
},
(a1, a2) -> null, // Not used, therefore not working scaffold
a -> a
);
MyResult result = collection.stream().collect(myCollector);
Immerhin fühlt es sich nicht idiomatisch an.
Neue Fragen
java
Java ist eine Programmiersprache auf hoher Ebene. Verwenden Sie dieses Tag, wenn Sie Probleme haben, die Sprache selbst zu verwenden oder zu verstehen. Dieses Tag wird selten alleine verwendet und wird am häufigsten in Verbindung mit [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] und [maven] verwendet.