【问题标题】:From for loop to Java 8 Stream example从 for 循环到 Java 8 Stream 示例
【发布时间】:2016-09-16 22:01:11
【问题描述】:

我想要一个 Java 8 Streams 的简单示例来理解它。我有返回免费出租车的代码。我想用使用 Java 8 流的等效代码替换这个 for 循环:

private List<Taxi> taxis = new ArrayList<Taxi>();

Taxi scheduleTaxi(){
    for (Taxi taxi : taxis) {
        if (taxi.isFree()) {
            return taxi;
        }
    }
    return null;
}

我遍历taxis 的列表,并评估taxi 是否符合条件。如果条件适用,我会停止循环并返回taxi

有什么建议吗?

【问题讨论】:

  • return taxis.stream().filter(Taxi::isFree).findFirst().orElse(null);。最后一个不是Stream方法,而是Optional方法。
  • 如果你要使用Stream,Andreas 是正确的,但你可能应该放弃orElse(null),而是返回Optional&lt;Taxi&gt;,因为它会给你一些方便的方法,比如ifPresent
  • @4castle 我决定写一个long answer,并采纳了你的建议。

标签: java for-loop java-8 java-stream


【解决方案1】:

使用最新的IntelliJ IDEA 2016.3 EAP(社区版或终极版),您可以自动转换它。只需将光标放在你的 for 循环上:

按 Alt-Enter 并选择“替换为 findFirst()”:

瞧,完成了!

免责声明:我是 IntelliJ IDEA 开发人员。

【讨论】:

    【解决方案2】:

    你要找的是这个:

    return taxis.stream()
                .filter(Taxi::isFree)
                .findFirst()
                .orElse(null);
    

    这里是表达式步骤的列表及其返回类型和到 javadoc 的链接

    表达步骤       | 类型                | 替代方案
    taxis                         | List&lt;Taxi&gt;
    stream()               | Stream&lt;Taxi&gt;   | parallelStream()
    filter(Taxi::isFree) | Stream&lt;Taxi&gt;
    findFirst()           | Optional&lt;Taxi&gt; | findAny()
    orElse(null)          | Taxi             | 无,见下文


    filter(Taxi::isFree) 调用使用的是method reference
    也可以使用lambda expression

    filter(t -> t.isFree())
    

    或使用 lambda 表达式块

    filter(t -> {
        return t.isFree();
    })
    

    参数也可以指定类型,更明确:

    filter((Taxi t) -> { return t.isFree(); })
    

    这使它看起来更像anonymous class,它相当于:

    filter(new Predicate<Taxi>() {
        @Override
        public boolean test(Taxi t) {
            return t.isFree();
        }
    })
    

    作为@4castle mentioned in a comment,根据您的scheduleTaxi() 方法的需要,您可能希望更改返回类型并跳过最后一步,以使其对可能无法找到的调用者明确出租车。

    Optional<Taxi> scheduleTaxi() {
        return taxis.stream().filter(Taxi::isFree).findFirst();
    }
    

    【讨论】:

    • 我知道这与 OPs 代码相同,但文字只是提到了寻找免费出租车。如果一些随机性是可以的并且出租车列表相当大,那么并行流和使用findAny 方法与findFirst 方法可能会有一些价值。
    • @AaronDavis 这就是为什么我将parallelStream()findAny() 列为alternatives,但显示的主要调用与原始代码直接等效。我留给这个答案的读者阅读各种方法的javadoc并自己了解差异。他们总是可以在 StackOverflow 上提出问题,然后他们对这些差异有具体的问题。
    • 哈..我错过了你答案的后半部分。这将教会我在没有完全阅读的情况下在手机上评论答案:-)
    【解决方案3】:

    评论已经说过了,但我会稍微解释一下

    private List<Taxi> taxis = new ArrayList<Taxi>();
    Optional<Taxi> optTaxi = taxis.stream().filter(taxi -> taxi.isFree()).findFirst() //or findAny()
    

    这是逻辑上发生的事情:从列表中获取流后,您使用filter,它基本上接受条件,检查列表中的哪些项目符合条件,并返回仅包含这些项目的流。然后findFirst/Any 抓取第一个/任何项目并将其作为Optional 返回。如果没有项目“存活”过滤,则Optional 将包含null

    请注意,代码执行的顺序与我描述的不同,因为流的工作方式不同。如果你这样做 filter(...).filter(...).filter(...) 它不会一遍又一遍地迭代,只是一次。

    回到你的代码:你可以返回 Optional&lt;Taxi&gt; 本身或解压它并返回 Taxi 对象,它可以是 null,这取决于你想要什么。

    【讨论】:

      猜你喜欢
      • 2018-09-17
      • 2019-03-20
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2015-02-17
      • 2019-03-05
      • 2020-04-05
      • 2021-03-27
      相关资源
      最近更新 更多