218

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

3 Answers 3

394

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. 
Sign up to request clarification or add additional context in comments.

21 Comments

Can you give me an example for Criteria, please? It should represent something like for(Stop s:listofstops){ if(s.name.equals("Linz") return r }
Stops is another class, the method filter is invokaded in Train but i want to walk through all Stop elements of the SortedSet stops
Turns out I am wrong - lazy streams prevent the inefficiency: stackoverflow.com/questions/23696317/…
@alexpfx you can use .findFirst().orElse(yourBackUpGoesHere);. That can also be null .findFirst().orElse(null);
@iammrmehul No. findFirst() returns an Optional object (JavaDoc), which might be empty. In this case the call to get() will throw the NPE. To prevent that from happening, use orElse() instead of get() and provide a fallback object (like orElse(new Station("dummy", -1)), or store the result of findFirst() in a variable and check it with isEmpty() before calling get()
|
10

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.

4 Comments

With the second one, I get a message "create local var" s
@user2147674 Is that an error message? Or is the compiler just informing you that it's creating a new sort-of "local variable" s to use with the lambda? It doesn't really look like an error to me, but I apparently am not using the same compiler as you are.
@user2147674 That's pretty strange. I'm able to use the second example (with findFirst().get() applied after filter), and I don't get any errors. The third example works for me too.
@ajb perhaps I am never the first so I am not able to see anything like "first" here
9

I think this is the best way:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.