Pobierz pierwszy element spełniający kryteria

122

Jak zdobyć pierwszy element spełniający kryteria w strumieniu? Próbowałem tego, ale nie działa

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

Kryteria te nie działają, metoda filtru jest wywoływana w klasie innej niż Stop.

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;
}

}
user2147674
źródło

Odpowiedzi:

215

To może być to, czego szukasz:

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



Przykład:

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);
}

Wynik to:

At the first stop at Station1 there were 250 passengers in the train.
ifloop
źródło
Czy możesz podać przykład dla Kryteriów? Powinien przedstawiać coś takiego jak dla (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674
1
Stops to kolejna klasa, filtr metody jest wywoływany w Train, ale chcę przejść przez wszystkie elementy Stop przystanków
SortedSet
2
Okazuje się, że się mylę - leniwe strumienie zapobiegają nieefektywności: stackoverflow.com/questions/23696317/…
Skychan
2
@alexpfx, którego możesz użyć .findFirst().orElse(yourBackUpGoesHere);. To też może być zerowe .findFirst().orElse(null);
ifloop
1
@iammrmehul No. findFirst()zwraca opcjonalny obiekt ( JavaDoc ), który może być pusty. W tym przypadku wywołanie get()wyrzuci NPE. Aby temu zapobiec, użyj orElse()zamiast tego get()obiektu zastępczego (takiego jak orElse(new Station("dummy", -1)) i podaj go , lub zapisz wynik findFirst()w zmiennej i sprawdź ją isEmpty()przed wywołaniemget()
ifloop
7

Kiedy piszesz wyrażenie lambda, lista argumentów po lewej stronie ->może być listą argumentów w nawiasach (prawdopodobnie pustą) lub pojedynczym identyfikatorem bez żadnych nawiasów. Ale w drugiej formie nie można zadeklarować identyfikatora z nazwą typu. A zatem:

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

ma nieprawidłową składnię; ale

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

jest poprawne. Lub:

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

jest również poprawne, jeśli kompilator ma wystarczającą ilość informacji, aby określić typy.

ajb
źródło
W przypadku drugiego otrzymuję komunikat „utwórz
zmienną
@ user2147674 Czy to komunikat o błędzie? A może kompilator po prostu informuje Cię, że tworzy nowy rodzaj „zmiennej lokalnej” sdo użycia z lambdą? Dla mnie to nie wygląda na błąd, ale najwyraźniej nie używam tego samego kompilatora co ty.
ajb
1
@ user2147674 To dość dziwne. Mogę użyć drugiego przykładu (z findFirst().get()zastosowanym po filter) i nie otrzymuję żadnych błędów. Trzeci przykład też mi odpowiada.
ajb
3

Myślę, że to najlepszy sposób:

this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);
Martin Volek
źródło