问题
I would like a simple example for Java 8 Streams
to understand it. I have this code that returns a free taxi. I would like to replace this for loop with equivalent code that uses Java 8 streams :
private List<Taxi> taxis = new ArrayList<Taxi>();
Taxi scheduleTaxi(){
for (Taxi taxi : taxis) {
if (taxi.isFree()) {
return taxi;
}
}
return null;
}
I iterate over a list of taxis
, and evaluate if taxi
respects the condition. If the condition applies, I stop the loop and return taxi
.
Any suggestions?
回答1:
What you are looking for is this:
return taxis.stream()
.filter(Taxi::isFree)
.findFirst()
.orElse(null);
Here is a list of the expression steps with their return type and links to javadoc:
Expression Step | Type | Alternativetaxis
| List<Taxi>
stream() | Stream<Taxi> | parallelStream()
filter(Taxi::isFree) | Stream<Taxi>
findFirst() | Optional<Taxi> | findAny()
orElse(null) | Taxi
| none, see below
The filter(Taxi::isFree)
call is using a method reference.
It can also be written using a lambda expression:
filter(t -> t.isFree())
or using a lambda expression block:
filter(t -> {
return t.isFree();
})
The parameter can also specify a type, to be more explicit:
filter((Taxi t) -> { return t.isFree(); })
which makes it look more like the anonymous class it's equivalent to:
filter(new Predicate<Taxi>() {
@Override
public boolean test(Taxi t) {
return t.isFree();
}
})
As @4castle mentioned in a comment, depending on the needs of your scheduleTaxi()
method, you might want to change the return type and skip the last step, to make it explicit to the caller that it might not be able to find a taxi.
Optional<Taxi> scheduleTaxi() {
return taxis.stream().filter(Taxi::isFree).findFirst();
}
回答2:
Using the newest IntelliJ IDEA 2016.3 EAP (either Community edition or Ultimate edition), you can convert it automatically. Just put the cursor on your for-loop:
Press the Alt-Enter and select "Replace with findFirst()":
Voila, it's done!
Disclaimer: I'm IntelliJ IDEA developer.
回答3:
Comments kinda said it already, but I'll explain a bit more:
private List<Taxi> taxis = new ArrayList<Taxi>();
Optional<Taxi> optTaxi = taxis.stream().filter(taxi -> taxi.isFree()).findFirst() //or findAny()
Here is what happens logically: after getting a stream from your list, you use filter
which basically takes conditions, checks which of the items in your list meet them, and returns a stream with only these items. Then findFirst/Any
grabs the first/any item and returns it as an Optional
. If no items "survive" the filtering, that Optional
will contain null
.
Just mind you that the order of code execution is not the same as I described because streams work differently. If you do filter(...).filter(...).filter(...)
it won't iterate over and over, just one time.
Back to your code: you can return the Optional<Taxi>
itself or unpack it and return the Taxi
object, which can be null
depending on what you want.
来源:https://stackoverflow.com/questions/39540691/from-for-loop-to-java-8-stream-example