Is there an efficient way to get elements from one index to another index in a collection without changing it to an ArrayList?

Tags: ,



I’m trying to implement pagination within a java/spring boot app on a Collection that is returned from a function. I want to get pages that are ordered by each elements “startTime”. So if the user asks for page 2 and each page has 10 items in it, then I would want to give the user the items with the top 10-20 most recent start times. I’ve since tried two approaches: a) Converting the returned collection into an array and then using IntStream on it to get elements from one index to another.

final exampleClass[] example = exampleCollection.toArray(new exampleClass[0]);
Collection<exampleClass> examplePage = IntStream.range(start, end)
    ...

b) Converting the returned collection into an ArrayList and then using Pageable/PageRequest to create a new page from that ArrayList.

The problem is that these seem very inefficient since I first have to change the Collection to an ArrayList or array and then operate on it. I would like to know if there are more efficient ways to turn collections into structures that I can iterate on using indices so that I can implement pagination. Or, if there are some Spring functions for creating pages that don’t require non-Collection parameters. However, I can’t find any Spring functions for creating pages that do.

Also, is there any difference in runtime between

List<exampleClass> x = new ArrayList<>(exampleCollection);

and

 List<exampleClass> x = (List<exampleClass>)exampleCollection;

Answer

I would like to know if there are more efficient ways to turn collections into structures that I can iterate on using indices

The only efficient way is to check by instanceof if your collection is indeed a List. If it is, then you can cast it, and simply use e.g. sublist(start, stop) to produce your paginated result.

Please note that accessing an element by its index might not be efficient either. In a LinkedList, accessing an element is a O(N) operation, so accesing M elements by index produces a O(M*N) operation, whereas using sublist() is a O(M+N) operation.

There is a specialization of the List interface that is used to mark lists that are fast at being accessed by index, and that is : RandomAccess, you may or may not want to check on that to decide on the best strategy.

Also, is there any difference in runtime between

List x = new ArrayList<>(exampleCollection);

and

List<exampleClass> x = (List<exampleClass>)exampleCollection;

There absolutely is.

The second is a cast, and has virtually no cost. Just beware that x and exampleCollection are one and the same object (modifying one is the same as modifying the other). Obviously, a cast may fail with a ClassCastException if exampleCollection is not actually a list.

The first performs a copy, which has a cost in both CPU (traversal of exampleCollection) and memory (allocating an array of the collection’s size). Both are pretty low for small collections, but your mileage may vary.

In this copy case, modifying one collection does nothing to the other, you get a copy.



Source: stackoverflow