当数字等于 0 时,如何使用流跳过 limit(number) 调用?

ran*_*er1 20 java java-8 java-stream

我有一些 Java 代码从items. 它基于以下条件限制它们maxNumber

items.stream()
     .map(this::myMapper)
     .filter(item -> item != null)
     .limit(maxNumber)
     .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

它工作正常,但问题是:有没有办法跳过限制maxNumber == 0

我知道我可以这样做:

if (maxNumber == 0) {
    items.stream()
         .map(this::myMapper)
         .filter(item -> item != null)
         .collect(Collectors.toList());
} else {
    items.stream()
         .map(this::myMapper)
         .filter(item -> item != null)
         .limit(maxNumber)
         .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

但也许有更好的方法,您有什么想法吗?

Kay*_*man 21

不,流管道不允许实际跳过管道的任何部分,因此您被迫在步骤中使用条件逻辑并limit()在管道中包含始终,或者在部分构建流比问题中的 if/else 更清晰(恕我直言)

Stream<Item> s = items.stream()
         .map(this::myMapper)
         .filter(Objects::nonNull);

if(maxNumber > 0) {
    s = s.limit(maxNumber);
}

List<Item> l = s.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

在像这里这样的简单情况下,它没有太大区别,但您经常看到常规代码集合通过方法传递,转换为流,然后返回到集合。在这种情况下,最好分部分使用流,直到您确实需要collect()


Jea*_*nès 16

我想

.limit(maxNumber == 0 ? Long.MAX_VALUE : maxNumber)
Run Code Online (Sandbox Code Playgroud)

会解决这个问题,因为你极不可能处理超过 2^63-1 个元素的流......

至少要小心并行流... API 文档中的注释说:

API 注意:虽然limit()在顺序流管道上通常是一种廉价的操作,但在有序并行管道上可能会非常昂贵,特别是对于 maxSize 的大值......