From for loop to Java 8 Stream example

若如初见. 提交于 2021-02-04 16:14:12

问题


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                    | Alternative
taxis                           | 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!