英文:
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<MyCustomClass> 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) -> { throw new RuntimeException("存在过多的值"); })
.orElseThrow(() -> { throw new RuntimeException("不存在值"); });
英文:
You can use reduce(accumulator)
and orElseThrow(exceptionSupplier)
to ensure the stream produces exactly one result.
MyCustomClass customClass = list.stream()
.reduce((a,b) -> { throw new RuntimeException("Too many values present"); })
.orElseThrow(() -> { throw new RuntimeException("No value present"); });
答案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<String> strings = new ArrayList<>();
Optional<String> maybeFirst = strings.stream().findFirst();
// we now have an optional, lets force a value
String value = maybeFirst.orElseThrow(IllegalArgumentException::new);
// if there isn't a value, we'll throw an illegal argument exception.
This can collapsed into the following.
String value = strings.stream()
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("There must be at least one string."));
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) -> { 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);} );
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论