Récupérer le premier élément qui correspond aux critères

122

Comment obtenir le premier élément qui correspond à un critère dans un flux? J'ai essayé mais ne fonctionne pas

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

Ce critère ne fonctionne pas, la méthode de filtrage est appelée dans une autre classe que 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
la source

Réponses:

215

C'est peut-être ce que vous recherchez:

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



Un exemple:

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

La sortie est:

At the first stop at Station1 there were 250 passengers in the train.
ifloop
la source
Pouvez-vous me donner un exemple de critères, s'il vous plaît? Cela devrait représenter quelque chose comme pour (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674
1
Les arrêts sont une autre classe, le filtre de méthode est invokadé dans Train mais je veux parcourir tous les éléments Stop des arrêts
SortedSet
2
Il s'avère que je me trompe - les flux paresseux empêchent l'inefficacité: stackoverflow.com/questions/23696317/…
Skychan
2
@alexpfx que vous pouvez utiliser .findFirst().orElse(yourBackUpGoesHere);. Cela peut également être nul .findFirst().orElse(null);
ifloop
1
@iammrmehul No. findFirst()renvoie un objet facultatif ( JavaDoc ), qui peut être vide. Dans ce cas, l'appel à get()lancera le NPE. Pour éviter que cela ne se produise, utilisez à la orElse()place de get()et fournissez un objet de secours (comme orElse(new Station("dummy", -1)), ou stockez le résultat de findFirst()dans une variable et vérifiez-le avec isEmpty()avant d'appelerget()
ifloop
7

Lorsque vous écrivez une expression lambda, la liste d'arguments à gauche de ->peut être soit une liste d'arguments entre parenthèses (éventuellement vide), soit un identificateur unique sans aucune parenthèse. Mais dans la seconde forme, l'identifiant ne peut pas être déclaré avec un nom de type. Donc:

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

est une syntaxe incorrecte; mais

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

est correct. Ou:

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

est également correct si le compilateur dispose de suffisamment d'informations pour déterminer les types.

ajb
la source
Avec le second, je reçois un message "create local var" s
user2147674
@ user2147674 Est-ce un message d'erreur? Ou est-ce que le compilateur vous informe simplement qu'il crée une nouvelle sorte de "variable locale" sà utiliser avec le lambda? Cela ne ressemble pas vraiment à une erreur pour moi, mais je n'utilise apparemment pas le même compilateur que vous.
ajb
1
@ user2147674 C'est assez étrange. Je suis capable d'utiliser le deuxième exemple (avec findFirst().get()appliqué après filter) et je n'obtiens aucune erreur. Le troisième exemple fonctionne aussi pour moi.
ajb
3

Je pense que c'est le meilleur moyen:

this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);
Martin Volek
la source