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?

3
sschmeck 19 Apr. 2018 im 16:01

5 Antworten

Beste Antwort

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"));
10
YCF_L 19 Apr. 2018 im 16:22

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

1
Abishek ram R 19 Apr. 2018 im 13:14

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.

0
daniu 19 Apr. 2018 im 13:07

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());
0
Garreth Golding 19 Apr. 2018 im 13:11

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.

0
sschmeck 19 Apr. 2018 im 14:03