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

3

我需要对列表页面进行处理。因此,我想知道以下两种方式在性能和最佳实践方面哪种更好:

  1. Original Answer
  2. 使用jQuery的.hide()方法
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
我会说stream().skip(offset * pageSize).limit(pageSize)需要较少的验证,因为超出范围的值将导致一个空的流 - 对于subList(...),您需要检查参数是否在列表的边界内。从性能角度来看,我猜subList对于ArrayList可能更快,但skip()对于LinkedList可能同样快甚至更快。我建议在这里不要关注性能,除非您面临真正的问题。相反,您应该关注其他属性,比如Lino评论的:子列表是由列表支持的视图。 - Thomas
3
如果很重要,就试试它们,并看看哪一个更快。这可能取决于您正在使用的List实现以及边界变量的值。至少对于java.util.ArrayListsubList方法是O(1)的。 - khelwood
1个回答

3
区别在于流操作的顺序。Java Stream API.指出skip是便宜的。
虽然在顺序流管道上,skip()通常是一个便宜的操作,但对于有序并行管道来说,特别是对于大量的n值,skip(n)可能会非常昂贵,因为skip(n)被限制为跳过遇到顺序中的前n个元素而不是任何n个元素。如果使用无序流源(例如generate(Supplier))或使用BaseStream.unordered()删除排序约束,则在并行管道中使用skip()可能会导致显着的加速,如果你的情况允许的话。如果需要与遭遇顺序一致,并且您在并行管道中使用skip()时遇到了性能或内存利用不佳的情况,请使用BaseStream.sequential()切换到顺序执行,这可能会改善性能。

Limit: 返回由该流的元素组成的流,同时在从生成的流中消耗每个元素时执行提供的操作。
使用流而不是子列表的一个好处是,您可以应用过滤器和逻辑,并且它可能比制作子列表更便宜。虽然流按函数顺序发生,但某些元素可能会被过滤掉,因此您只需要执行一次流。而在列表项中,您可能需要多次循环并使用多个对象来临时保存项目;通常情况下,还要循环同一项不需要的功能。
虽然您的问题非常具体。这些原则也适用于列表中在幕后发生的事情。流的威力。在幕后,仍然可能有来自流的多个对象;但是当对元素集合进行复杂操作时,程序员的复杂性被消除了。简单地说,它可以替换许多后续的for循环,我们使用顶级处理元素。它们确实是实用工具。流可以替换for循环

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接