Holen Sie sich das erste Element, das den Kriterien entspricht


120

Wie erhalte ich das erste Element, das einem Kriterium in einem Stream entspricht? Ich habe es versucht, aber es funktioniert nicht

this.stops.stream().filter(Stop s-> s.getStation().getName().equals(name));

Dieses Kriterium funktioniert nicht. Die Filtermethode wird in einer anderen Klasse als Stop aufgerufen.

public class Train {

private final String name;
private final SortedSet<Stop> stops;

public Train(String name) {
    this.name = name;
    this.stops = new TreeSet<Stop>();
}

public void addStop(Stop stop) {
    this.stops.add(stop);
}

public Stop getFirstStation() {
    return this.getStops().first();
}

public Stop getLastStation() {
    return this.getStops().last();
}

public SortedSet<Stop> getStops() {
    return stops;
}

public SortedSet<Stop> getStopsAfter(String name) {


    // return this.stops.subSet(, toElement);
    return null;
}
}


import java.util.ArrayList;
import java.util.List;

public class Station {
private final String name;
private final List<Stop> stops;

public Station(String name) {
    this.name = name;
    this.stops = new ArrayList<Stop>();

}

public String getName() {
    return name;
}

}

Antworten:


213

Dies könnte das sein, wonach Sie suchen:

yourStream
    .filter(/* your criteria */)
    .findFirst()
    .get();



Ein Beispiel:

public static void main(String[] args) {
    class Stop {
        private final String stationName;
        private final int    passengerCount;

        Stop(final String stationName, final int passengerCount) {
            this.stationName    = stationName;
            this.passengerCount = passengerCount;
        }
    }

    List<Stop> stops = new LinkedList<>();

    stops.add(new Stop("Station1", 250));
    stops.add(new Stop("Station2", 275));
    stops.add(new Stop("Station3", 390));
    stops.add(new Stop("Station2", 210));
    stops.add(new Stop("Station1", 190));

    Stop firstStopAtStation1 = stops.stream()
            .filter(e -> e.stationName.equals("Station1"))
            .findFirst()
            .get();

    System.out.printf("At the first stop at Station1 there were %d passengers in the train.", firstStopAtStation1.passengerCount);
}

Ausgabe ist:

At the first stop at Station1 there were 250 passengers in the train.

Können Sie mir bitte ein Beispiel für Kriterien geben? Es sollte so etwas wie für (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674

1
Stops ist eine andere Klasse, der Methodenfilter ist in Train aufgerufen, aber ich möchte durch alle Stop-Elemente der SortedSet-Stopps gehen
user2147674

2
Es stellt sich heraus, dass ich falsch liege
Skychan

2
@alexpfx können Sie verwenden .findFirst().orElse(yourBackUpGoesHere);. Das kann auch null sein .findFirst().orElse(null);
ifloop

1
@iammrmehul No. findFirst()gibt ein optionales Objekt ( JavaDoc ) zurück, das möglicherweise leer ist. In diesem Fall wird der Aufruf von get()die NPE auslösen. Um dies zu verhindern, verwenden Sie orElse()anstelle von get()und stellen Sie ein Fallback-Objekt (wie orElse(new Station("dummy", -1)) bereit , oder speichern Sie das Ergebnis von findFirst()in einer Variablen und überprüfen Sie es isEmpty()vor dem Aufruf mitget()
ifloop

7

Wenn Sie einen Lambda-Ausdruck schreiben, kann die Argumentliste links ->davon entweder eine Argumentliste in Klammern (möglicherweise leer) oder ein einzelner Bezeichner ohne Klammern sein. In der zweiten Form kann der Bezeichner jedoch nicht mit einem Typnamen deklariert werden. So:

this.stops.stream().filter(Stop s-> s.getStation().getName().equals(name));

ist falsche Syntax; aber

this.stops.stream().filter((Stop s)-> s.getStation().getName().equals(name));

ist richtig. Oder:

this.stops.stream().filter(s -> s.getStation().getName().equals(name));

ist auch richtig, wenn der Compiler über genügend Informationen verfügt, um die Typen herauszufinden.


Mit dem zweiten bekomme ich eine Nachricht "create local var" s
user2147674

@ user2147674 Ist das eine Fehlermeldung? Oder informiert Sie der Compiler nur darüber, dass er eine neue Art von "lokaler Variable" erstellt s, die mit dem Lambda verwendet werden soll? Es sieht für mich nicht wirklich nach einem Fehler aus, aber ich verwende anscheinend nicht den gleichen Compiler wie Sie.
Ajb

1
@ user2147674 Das ist ziemlich seltsam. Ich kann das zweite Beispiel verwenden (mit findFirst().get()angewendet nach filter) und erhalte keine Fehler. Das dritte Beispiel funktioniert auch für mich.
Ajb

3

Ich denke, das ist der beste Weg:

this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.