Recupera il primo elemento che corrisponde ai criteri


121

Come ottenere il primo elemento che corrisponde a un criterio in uno stream? L'ho provato ma non funziona

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

Questo criterio non funziona, il metodo del filtro viene richiamato in una classe diversa da 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;
}

}

Risposte:


214

Questo potrebbe essere quello che stai cercando:

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



Un esempio:

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

L'output è:

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

Puoi farmi un esempio per Criteria, per favore? Dovrebbe rappresentare qualcosa di simile a (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674

1
Stops è un'altra classe, il filtro del metodo viene richiamato in Train ma voglio passare attraverso tutti gli elementi Stop delle fermate
SortedSet

2
Si scopre che mi sbaglio - flussi pigri impediscono l'inefficienza: stackoverflow.com/questions/23696317/...
Skychan

2
@alexpfx che puoi usare .findFirst().orElse(yourBackUpGoesHere);. Può anche essere nullo .findFirst().orElse(null);
ifloop

1
@iammrmehul No. findFirst()restituisce un oggetto opzionale ( JavaDoc ), che potrebbe essere vuoto. In questo caso la chiamata a get()lancerà l'NPE. Per evitare che ciò accada, usa orElse()invece di get()e fornisci un oggetto di fallback (come orElse(new Station("dummy", -1)), oppure memorizza il risultato di findFirst()in una variabile e controllalo isEmpty()prima di chiamareget()
ifloop

7

Quando scrivi un'espressione lambda, l'elenco di argomenti a sinistra di ->può essere un elenco di argomenti tra parentesi (possibilmente vuoto) o un singolo identificatore senza parentesi. Ma nella seconda forma, l'identificatore non può essere dichiarato con un nome di tipo. Così:

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

è una sintassi errata; ma

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

è corretto. O:

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

è corretto anche se il compilatore ha abbastanza informazioni per capire i tipi.


Con il secondo, ricevo un messaggio "crea var locale" s
user2147674

@ user2147674 È un messaggio di errore? O il compilatore ti sta solo informando che sta creando un nuovo tipo di "variabile locale" sda utilizzare con lambda? Non mi sembra davvero un errore, ma a quanto pare non sto usando lo stesso compilatore di te.
ajb

1
@ user2147674 È piuttosto strano. Sono in grado di utilizzare il secondo esempio (con findFirst().get()applicato dopo filter) e non ottengo alcun errore. Il terzo esempio funziona anche per me.
ajb

3

Penso che questo sia il modo migliore:

this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.