Java 8流,List.subList或Stream.skip()。limit()

时间:2019-03-26 13:39:52

标签: java java-8 java-stream

我需要在列表的页面上进行处理。 因此,我想知道在以下两者之间(在性能和良好实践方面)哪个更好:

public List<Other> function(List<Something> somethingList, 
                            int offset, int pageSize) {
    return somethingList.stream().skip(offset * pageSize).limit(pageSize)
        .map(s -> doSomething(s)).collect(Collectors.toList());
}

或:

public List<Other> function(List<Something> somethingList, 
                            int offset, int pageSize) {
    return somethingList.subList(offset * pageSize, offset * pageSize + pageSize)
        .stream().map(s -> doSomething).collect(Collectors.toList());
}

我省略了对偏移量和页面大小的自愿验证。

编辑:性能并不是至关重要的需求,我的问题还在于清晰度,维护和良好实践。我更喜欢流的方式,尤其是因为它需要较少的验证。但我更希望确保这不是性能的真正损失或维护性/清洁性较差的东西。

1 个答案:

答案 0 :(得分:2)

区别在于流操作的排序方式。 Java Stream API。跳过的国家很便宜。

  

尽管skip()在顺序流管道上通常是便宜的操作,但在有序并行管道上却可能非常昂贵,尤其是对于较大的n值,因为skip(n)不仅被限制为不仅可以跳过n个元素,而且还可以跳过遇到顺序中的前n个元素。如果情况的语义允许,则使用无序流源(例如generate(Supplier))或使用BaseStream.unordered()删除排序约束可能会导致并行管道中skip()的显着加速。如果需要与遇到顺序保持一致,并且在并行管道中使用skip()遇到性能低下或内存使用率不足的情况,则切换为使用BaseStream.sequential()顺序执行可能会提高性能。

  

Limit:返回一个由该流的元素组成的流,并在从结果流中消耗掉元素后,另外对每个元素执行提供的操作。

在子列表上使用流的一个好处是,您可以应用过滤器和/或您询问的逻辑,与创建子列表相比,它可能会更便宜。尽管流按功能顺序发生,但某些元素可能会被过滤掉,而您只需要执行一次流。在列出项目时,您可能不得不循环多次并使用多个对象临时保留这些项目;通常会遍历该项目相同的不需要功能。

您的问题非常具体。这些相同的原则将适用于列表中的实际情况。 Power of streams。在引擎盖下,流中可能仍然有多个对象。但是当对一组元素执行复杂的操作时,复杂性就从程序员那里移走了。简而言之,它可以替代许多背靠背的循环,而在循环中我们使用顶级过程元素。它们确实是实用程序。 Streams can replace for loops