通过谓词查找第一个元素

新手上路,请多包涵

我刚开始玩 Java 8 lambda,我正在尝试用函数式语言实现一些我习惯的东西。

例如,大多数函数式语言都有某种对序列或返回第一个元素的列表进行操作的查找函数,其谓词是 true 。我能看到在 Java 8 中实现此目的的唯一方法是:

 lst.stream()
    .filter(x -> x > 5)
    .findFirst()

然而,这对我来说似乎效率低下,因为过滤器将扫描整个列表,至少在我看来是这样(这可能是错误的)。有没有更好的办法?

原文由 siki 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 329
2 个回答

不,过滤器不会扫描整个流。它是一个中间操作,它返回一个惰性流(实际上所有的中间操作都返回一个惰性流)。为了说服你,你可以简单地做以下测试:

 List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);
int a = list.stream()
            .peek(num -> System.out.println("will filter " + num))
            .filter(x -> x > 5)
            .findFirst()
            .get();
System.out.println(a);

哪些输出:

 will filter 1
will filter 10
10

您会看到实际上只处理了流的前两个元素。

所以你可以采用你的方法,这非常好。

原文由 Alexis C. 发布,翻译遵循 CC BY-SA 3.0 许可协议

然而,这对我来说似乎效率低下,因为过滤器将扫描整个列表

不,它不会 - 一旦找到满足谓词的第一个元素,它就会“中断”。您可以在 流包 javadoc 中阅读更多关于懒惰的信息,特别是(强调我的):

许多流操作,如过滤、映射或重复删除,可以延迟实现,从而提供优化机会。例如,“查找第一个包含三个连续元音的字符串”不需要检查所有输入字符串。 Stream 操作分为中间(Stream-producing)操作和终端(value-or side-effect-producing)操作。 中间操作总是懒惰的。

原文由 wha‘eve’ 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题