Вилучити перший елемент, який відповідає критеріям


121

Як отримати перший елемент, який відповідає критеріям у потоці? Я спробував це, але не виходить

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

Цей критерій не працює, метод фільтра використовується в іншому класі, ніж 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;
}

}

Відповіді:


213

Це може бути те, що ви шукаєте:

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



Приклад:

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

Вихід:

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

Чи можете ви надати мені приклад для критеріїв, будь ласка? Він повинен представляти щось на зразок для (Stop s: listofstops) {if (s.name.equals ("Linz") return r}
user2147674

1
Зупиняється - це ще один клас, фільтр методів викликається у Train, але я хочу пройти всі елементи зупинки зупинок
SortedSet

2
Виявляється, я не права - ледачі потоки запобігти неефективність: stackoverflow.com/questions/23696317 / ...
Skychan

2
@alexpfx ви можете використовувати .findFirst().orElse(yourBackUpGoesHere);. Це також може бути недійсним .findFirst().orElse(null);
ifloop

1
@iammrmehul No. findFirst()повертає необов'язковий об'єкт ( JavaDoc ), який може бути порожнім. У цьому випадку заклик до get()кидає NPE. Щоб цього не сталося, використовуйте orElse()замість цього get()і надайте резервний об'єкт (наприклад orElse(new Station("dummy", -1)) або зберігайте результат findFirst()у змінній і перевіряйте це isEmpty()перед тим, як дзвонитиget()
ifloop

7

Коли ви пишете лямбда-вираз, список аргументів зліва від ->може бути або укрупненим списком аргументів (можливо, порожнім), або одним ідентифікатором без дужок. Але у другій формі ідентифікатор не може бути оголошений іменем типу. Таким чином:

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

неправильний синтаксис; але

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

правильно. Або:

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

також правильно, якщо у компілятора є достатньо інформації для з'ясування типів.


З другого, я отримую повідомлення "створити локальний var" s
user2147674

@ user2147674 Це повідомлення про помилку? Або компілятор просто інформує вас, що він створює новий сорт "локальної змінної" sдля використання з лямбда? Насправді це не схоже на помилку для мене, але я, мабуть, не використовую той самий компілятор, як і ви.
ajb

1
@ user2147674 Це досить дивно. Я можу використовувати другий приклад (із findFirst().get()застосованим після filter), і я не отримую помилок. Третій приклад працює і для мене.
ajb

3

Я думаю, що це найкращий спосіб:

this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.