Fetch first element of stream matching the criteria

JavaJava 8Java Stream

Java Problem Overview


How to get first element that matches a criteria in a stream? I've tried this but doesn't work

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

That criteria is not working, the filter method is invoked in an other class than 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;
}

}

Java Solutions


Solution 1 - Java

This might be what you are looking for:

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

And better, if there's a possibility of matching no element, in which case get() will throw a NPE. So use:

yourStream
    .filter(/* your criteria */)
    .findFirst()
    .orElse(null); /* You could also create a default object here */



An example:

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()
            .orElse(null);

    System.out.printf("At the first stop at Station1 there were %d passengers in the train.", firstStopAtStation1.passengerCount);
}

Output is:

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

Solution 2 - Java

When you write a lambda expression, the argument list to the left of -> can be either a parenthesized argument list (possibly empty), or a single identifier without any parentheses. But in the second form, the identifier cannot be declared with a type name. Thus:

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

is incorrect syntax; but

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

is correct. Or:

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

is also correct if the compiler has enough information to figure out the types.

Solution 3 - Java

I think this is the best way:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2147674View Question on Stackoverflow
Solution 1 - JavaifloopView Answer on Stackoverflow
Solution 2 - JavaajbView Answer on Stackoverflow
Solution 3 - JavaMartin VolekView Answer on Stackoverflow