Busque o primeiro elemento que corresponda aos critérios

121

Como obter o primeiro elemento que corresponde a um critério em um fluxo? Eu tentei isso mas não funciona

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

Esse critério não está funcionando, o método de filtro é chamado em uma classe diferente de 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
fonte

Respostas:

213

Isso pode ser o que você está procurando:

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



Um exemplo:

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

O resultado é:

At the first stop at Station1 there were 250 passengers in the train.
ifloop
fonte
Você pode me dar um exemplo de Critérios, por favor? Deve representar algo como para (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674
1
Stops é outra classe, o filtro de método é invocado em Train, mas eu quero percorrer todos os elementos Stop do SortedSet stops
user2147674
2
Acontece que estou errado - streams preguiçosos evitam a ineficiência: stackoverflow.com/questions/23696317/…
Skychan,
2
@alexpfx você pode usar .findFirst().orElse(yourBackUpGoesHere);. Isso também pode ser nulo .findFirst().orElse(null);
ifloop de
1
@iammrmehul No. findFirst()retorna um objeto opcional ( JavaDoc ), que pode estar vazio. Nesse caso, a chamada para get()lançará o NPE. Para evitar que isso aconteça, use em orElse()vez de get()e forneça um objeto substituto (como orElse(new Station("dummy", -1)) ou armazene o resultado de findFirst()em uma variável e verifique isEmpty()antes de chamarget()
ifloop
7

Quando você escreve uma expressão lambda, a lista de argumentos à esquerda de ->pode ser uma lista de argumentos entre parênteses (possivelmente vazia) ou um único identificador sem parênteses. Mas, na segunda forma, o identificador não pode ser declarado com um nome de tipo. Portanto:

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

é sintaxe incorreta; mas

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

está correto. Ou:

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

também está correto se o compilador tiver informações suficientes para descobrir os tipos.

ajb
fonte
Com o segundo, recebo uma mensagem "create local var" s
user2147674
@ user2147674 É uma mensagem de erro? Ou o compilador está apenas informando que está criando um novo tipo de "variável local" spara usar com o lambda? Realmente não parece um erro para mim, mas aparentemente não estou usando o mesmo compilador que você.
ajb
1
@ user2147674 Isso é muito estranho. Consigo usar o segundo exemplo (com findFirst().get()aplicado depois filter) e não recebo nenhum erro. O terceiro exemplo funciona para mim também.
ajb de
3

Acho que esta é a melhor maneira:

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