Java 8 流中的 LINQ Enumerable.Single() [重复]

Posted

技术标签:

【中文标题】Java 8 流中的 LINQ Enumerable.Single() [重复]【英文标题】:LINQs Enumerable.Single() in Java 8's Streams [duplicate] 【发布时间】:2015-05-07 03:22:53 【问题描述】:

我对 C# 的 LINQ 有一些经验,并且正在尝试学习 Java 8 的流 API。现在在 LINQ 中,我经常使用 Single() Method,它从序列中挑选出唯一的对象,如果流中没有唯一的对象,则抛出异常。

现在:

我认为 Java 8 的流没有这样的方法是否正确? 是否有获得此功能的首选替代方法? 自己实现这个是个好主意吗?

【问题讨论】:

确实有点回答我的问题 1) 方法不是开箱即用的 2) 很多选项,对于首选的内容没有共识,自定义收集器看起来不错 3) 实现自定义收集器是什么人们在建议。所以感谢链接,搜索它但显然不够好。我需要采取什么措施来确认这是重复的吗? 您还应该考虑 Brian Goetz 的答案(或者将其包装在一个简单的实用方法中);或使用 Guava Iterators 实用程序类;具有您正在寻找的 Single 行为。 T elem = Iterators.getOnlyElement(stream.iterator()); stream.collect(Collectors.toMap(()->"single", Functions.identity()).get("single") 如果有多个元素,也会抛出... 【参考方案1】:

这是获得此功能的一种方法:

Stream<String> stream = Stream.of ("first");
String single = stream.reduce((a,b)->throw new SomeException();)
                      .get();

这个想法是,如果有多个元素,reduce 会在 lambda 表达式中抛出异常。如果没有元素,get() 将抛出 NoSuchElementException

您也可以通过将代码更改为:

来更改没有元素时抛出的异常:
Stream<String> stream = Stream.of ("first");
String single = stream.reduce((a,b)->throw new SomeException();)
                      .orElseThrow(SomeException::new);

【讨论】:

为什么会这样:用于reduction 的associative 累积函数仅在有多个元素时才由流调用。如果有单个元素,则流解析为该元素。我们劫持此功能以引发异常而不是累积值。它既聪明又简洁,但可能会令人困惑,因为这不是 API 的预期用途。

以上是关于Java 8 流中的 LINQ Enumerable.Single() [重复]的主要内容,如果未能解决你的问题,请参考以下文章

从 java 8 流中的列表中过滤值

Java 8 并行流中的自定义线程池

如何使用 Java 8 lambda 从流中获取一系列项目?

Java 8:如何在流中使用异常抛出方法?

如何获取 Java 8 流中所有元素的字符串表示形式

Effective Java 第三版——46. 优先考虑流中无副作用的函数