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

huangapple go评论68阅读模式
英文:

Java stream get single element from collection

问题

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

List<MyCustomClass> list = OtherObject.getMyList();

if (list.size() != 1) {
    throw new RuntimeException();
}

MyCustomClass customClass = list.get(0);

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

英文:

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

List&lt;MyCustomClass&gt; list = OtherObject.getMyList();

if (list.size() != 1) {
throw new RuntimeException();
}

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) 来确保流产生且仅产生一个结果。

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

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

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

答案2

得分: 0

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

List<String> strings = new ArrayList<>();

Optional<String> maybeFirst = strings.stream().findFirst();
// 现在我们有了一个可选项,让我们强制获取一个值

String value = maybeFirst.orElseThrow(IllegalArgumentException::new);
// 如果没有值,我们会抛出非法参数异常。

这可以简化为以下形式。

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

希望对您有所帮助。

英文:

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

List&lt;String&gt; strings = new ArrayList&lt;&gt;();
       
Optional&lt;String&gt; maybeFirst = strings.stream().findFirst();
// we now have an optional, lets force a value

String value = maybeFirst.orElseThrow(IllegalArgumentException::new);
// if there isn&#39;t a value, we&#39;ll throw an illegal argument exception.

This can collapsed into the following.

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

Hope that helps.

答案3

得分: 0

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

list.stream().collect(
    Collector.of(ArrayList::new,
        (a, t) -> {
            if (!a.isEmpty())
                throw new RuntimeException();
            a.add(t);
        },
        (a, b) -> {
            throw new RuntimeException();
        },
        a -> {
            if (a.isEmpty())
                throw new RuntimeException();
            return a.get(0);
        })
);
英文:

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.

list.stream().collect(
    Collector.of( ArrayList::new, 
                  (a, t) -&gt; { if (!a.isEmpty())
                                  throw new RuntimeException();
                              a.add(t); },
                  (a, b) -&gt; { throw new RuntimeException(); },
                  a -&gt; { if( a.isEmpty() )
                             throw new RuntimeException();
                         return a.get(0);} );

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

发表评论

匿名网友

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

确定