Java 8 Spliterator(或类似的),如果只有一个值,则返回值

Ned*_*igg 5 java java-8 java-stream spliterator

我是singleOrEmpty流媒体运营商的忠实粉丝.它不在std lib中,但我发现它非常有用.如果流只有一个值,则返回该值Optional.如果它没有值或多于一个值,则返回Optional.empty().

Optional<Int> value = someList.stream().{singleOrEmpty}
[]     -> Optional.empty()
[1]    -> Optional.of(1)
[1, 1] -> Optional.empty()
etc.
Run Code Online (Sandbox Code Playgroud)

我之前问了一个关于它的问题,而@ThomasJungblut 想出了这个伟大的实现:

public static <T> Optional<T> singleOrEmpty(Stream<T> stream) {
    return stream.limit(2)
        .map(Optional::ofNullable)
        .reduce(Optional.empty(),
             (a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty());
}
Run Code Online (Sandbox Code Playgroud)

唯一的问题是,你必须把它放在通话的开头

singleOrEmpty(someList.stream().filter(...).map(...))
Run Code Online (Sandbox Code Playgroud)

而不是顺序结束

someList.stream().filter().map().singleOrEmpty()
Run Code Online (Sandbox Code Playgroud)

这使得它比其他流机制更难阅读.

那么作为这个流处理的新手,有没有人有任何技巧可以singleOrEmpty在一系列流转换结束时建立一个短路机制?

Mis*_*sha 6

它不会像限制(2)那样快,但你可以使用它 list.stream().filter(...).map(...).collect(singleOrEmpty())

static <T> Collector<T, ?, Optional<T>> singleOrEmpty() {
    return Collectors.collectingAndThen(
            Collectors.mapping(
                    Optional::of,
                    Collectors.reducing((a, b) -> Optional.empty())
            ),
            o -> o.orElseGet(Optional::empty)
    );
}

Stream.empty().collect(singleOrEmpty());   // Optional.empty
Stream.of(1).collect(singleOrEmpty());     // Optional[1]
Stream.of(1, 1).collect(singleOrEmpty());  // Optional.empty
Stream.of(1, 1).skip(1).collect(singleOrEmpty());  // Optional[1]
Run Code Online (Sandbox Code Playgroud)

对于它的价值,除非这是真正的性能关键代码,否则我个人更喜欢不那么聪明但更清晰的实现

static<T> Collector<T,?,Optional<T>> singleOrEmpty() {
    return Collectors.collectingAndThen(
            Collectors.toList(),
            lst -> lst.size() == 1
                    ? Optional.of(lst.get(0))
                    : Optional.empty()
    );
}
Run Code Online (Sandbox Code Playgroud)

  • 使用`Collectors.reducing(...)`的重载版本可以简化第一个收集器.我认为这个版本并不比你建议的第二个版本差(对于大块代码感到遗憾,我只是觉得它不值得单独回答).`静态<T>集电极<T,可选<T >> singleOrEmptyCollector(){返回Collectors.reducing(Optional.empty(),可选:: ofNullable,(优化,T) - > opt.isPresent()^吨.isPresent()?t:Optional.empty()); }` (2认同)
  • @StanislavLukyanov如果流有3个(或5个,7个等)元素,则收集器将失败.例如,`Stream.of(1,1,1).collect(...)`将返回Optional [1]而不是Optional.empty. (2认同)