我正试图在函数返回的Collection上的java/spring引导应用程序中实现分页。我想得到按每个元素排序的页面";startTime";。因此,如果用户要求第2页,并且每一页都有10个项目,那么我想给用户最近开始时间前10-20个的项目。此后,我尝试了两种方法:a( 将返回的集合转换为数组,然后对其使用IntStream将元素从一个索引获取到另一个索引。
final exampleClass[] example = exampleCollection.toArray(new exampleClass[0]);
Collection<exampleClass> examplePage = IntStream.range(start, end)
...
b( 将返回的集合转换为ArrayList,然后使用Pageable/PageRequest从该ArrayList创建新页面。
问题是,这些似乎效率很低,因为我首先必须将集合更改为ArrayList或数组,然后对其进行操作。我想知道是否有更有效的方法将集合转换为结构,我可以使用索引对其进行迭代,以便实现分页。或者,如果有一些Spring函数用于创建不需要非Collection参数的页面。然而,我找不到任何Spring函数来创建这样的页面。
此外,在运行时是否存在差异
List<exampleClass> x = new ArrayList<>(exampleCollection);
和
List<exampleClass> x = (List<exampleClass>)exampleCollection;
我想知道是否有更有效的方法将集合转换为可以使用索引迭代的结构
唯一有效的方法是通过instanceof
检查您的集合是否确实是List
。如果是,那么您可以强制转换它,只需使用例如sublist(start, stop)
来生成分页结果。
请注意,通过索引访问元素可能也不高效。在LinkedList
中,访问元素是O(N(运算,因此通过索引访问M个元素会产生O(M*N(运算;而使用sublist()
是O(M+N(运算。
List
接口有一个专门化的功能,用于标记索引访问速度快的列表,即:RandomAccess
,您可能希望也可能不希望检查它来决定最佳策略。
此外,在运行时是否存在差异
List x=新的ArrayList<gt;(exampleCollection(;
和
List<exampleClass> x = (List<exampleClass>)exampleCollection;
绝对存在.
第二个是铸件,几乎没有成本。只需注意x
和exampleCollection
是同一个对象(修改一个和修改另一个是一样的(。显然,如果exampleCollection
实际上不是一个列表,则转换可能会失败,并出现ClassCastException。
第一个执行复制,这在CPU(遍历exampleCollection
(和内存(分配集合大小的数组(方面都有成本。对于小型收藏来说,两者都很低,但你的里程数可能会有所不同。
在这种复制的情况下,修改一个集合对另一个集合没有任何作用,您得到了一个副本。
集合不必具有一致的迭代顺序:如果调用iterator()
两次,则可能会得到两个不同的序列。将集合转换为数组或列表是最佳解决方案。
至于第二个问题:这行代码:
List<exampleClass> x = new ArrayList<>(exampleCollection);
创建一个新的ArrayList,它是原始集合的浅拷贝。也就是说,它包含指向与原始集合相同对象的指针,但列表本身是新的,例如,您可以对列表进行排序,或添加或删除项,而不会影响原始集合。与相比
List<exampleClass> x = (List<exampleClass>)exampleCollection;
假设exampleCollection
实际上是一个List,这将为您提供一个指向具有新数据类型的列表的指针。如果您进行诸如排序、添加或删除项目之类的更改,您将在exampleCollection
中看到这些修改。另一方面,如果exampleCollection
不是List,则会出现运行时错误(ClassCastException(。