Java流从集合中获取单个元素

huangapple 未分类评论53阅读模式
英文:

Java stream get single element from collection

问题

我正在使用非流式方法从集合中获取单个元素。

  1. List<MyCustomClass> list = OtherObject.getMyList();
  2. if (list.size() != 1) {
  3. throw new RuntimeException();
  4. }
  5. MyCustomClass customClass = list.get(0);

除了这种多行方法,是否有一些通过流(streams)实现这个的方式?

英文:

I am using a non stream way to get single element from collection.

  1. List&lt;MyCustomClass&gt; list = OtherObject.getMyList();
  2. if (list.size() != 1) {
  3. throw new RuntimeException();
  4. }
  5. MyCustomClass customClass = list.get(0);

Instead of this multi liner approach, is there some way to achieve this via streams?

答案1

得分: 2

你可以使用 reduce(accumulator)orElseThrow(exceptionSupplier) 来确保流产生且仅产生一个结果。

  1. MyCustomClass customClass = list.stream()
  2. .reduce((a,b) -&gt; { throw new RuntimeException(&quot;存在过多的值&quot;); })
  3. .orElseThrow(() -&gt; { throw new RuntimeException(&quot;不存在值&quot;); });
英文:

You can use reduce(accumulator) and orElseThrow(exceptionSupplier) to ensure the stream produces exactly one result.

  1. MyCustomClass customClass = list.stream()
  2. .reduce((a,b) -&gt; { throw new RuntimeException(&quot;Too many values present&quot;); })
  3. .orElseThrow(() -&gt; { throw new RuntimeException(&quot;No value present&quot;); });

答案2

得分: 0

你可以尝试从findFirst()findAny()返回一个可选项。

  1. List<String> strings = new ArrayList<>();
  2. Optional<String> maybeFirst = strings.stream().findFirst();
  3. // 现在我们有了一个可选项,让我们强制获取一个值
  4. String value = maybeFirst.orElseThrow(IllegalArgumentException::new);
  5. // 如果没有值,我们会抛出非法参数异常。

这可以简化为以下形式。

  1. String value = strings.stream()
  2. .findFirst()
  3. .orElseThrow(() -> new IllegalArgumentException("至少必须有一个字符串。"));

希望对您有所帮助。

英文:

You could try returning an optional from findFirst() or findAny().

  1. List&lt;String&gt; strings = new ArrayList&lt;&gt;();
  2. Optional&lt;String&gt; maybeFirst = strings.stream().findFirst();
  3. // we now have an optional, lets force a value
  4. String value = maybeFirst.orElseThrow(IllegalArgumentException::new);
  5. // if there isn&#39;t a value, we&#39;ll throw an illegal argument exception.

This can collapsed into the following.

  1. String value = strings.stream()
  2. .findFirst()
  3. .orElseThrow(() -&gt; new IllegalArgumentException(&quot;There must be at least one string.&quot;));

Hope that helps.

答案3

得分: 0

我曾经寻找过一个只包含单个collect语句的版本,尽管结果并不像Andreas的解决方案那样简洁优雅。它使用了一个Collector的实现,将累积到一个单元素列表中,而组合器在有多于一个元素时会引发异常;完成器会在列表为空时引发异常。

  1. list.stream().collect(
  2. Collector.of(ArrayList::new,
  3. (a, t) -> {
  4. if (!a.isEmpty())
  5. throw new RuntimeException();
  6. a.add(t);
  7. },
  8. (a, b) -> {
  9. throw new RuntimeException();
  10. },
  11. a -> {
  12. if (a.isEmpty())
  13. throw new RuntimeException();
  14. return a.get(0);
  15. })
  16. );
英文:

I was looking for a version with a single collect statement, although it turned out not as concise or elegant as the solution by Andreas. It uses an implementation of Collector that accumulates to a one-element list, while the combiner raises an exception if we have more than one element; the finisher raises an exception when the list is empty.

  1. list.stream().collect(
  2. Collector.of( ArrayList::new,
  3. (a, t) -&gt; { if (!a.isEmpty())
  4. throw new RuntimeException();
  5. a.add(t); },
  6. (a, b) -&gt; { throw new RuntimeException(); },
  7. a -&gt; { if( a.isEmpty() )
  8. throw new RuntimeException();
  9. return a.get(0);} );

huangapple
  • 本文由 发表于 2020年4月11日 10:02:29
  • 转载请务必保留本文链接:https://java.coder-hub.com/61151206.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定