Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create List from a subarray without copying in java [closed]

I'm trying to initialize an ArrayList from an Array, but just the subarray, given the original array and subarray start and end index.

I can only think of doing something like this to create a new list from the subarray:

Arrays.asList(Arrays.copyOfRange(arr, i, j));

or just manually add elements to a list

List<Integer> result = new ArrayList<>(k);
for (int i = left; i < left + k; i++) {
    result.add(arr[i]);
}

Which obviously isn't very pretty. Is there better way to do it by just passing in array and indexes?

like image 326
Armo Avatar asked Dec 23 '22 11:12

Armo


1 Answers

"Better" depends on your requirements, and use case. Since you suggested using Arrays.asList(...), which returns a fixed size list, I will assume here that a fixed size list is sufficient for your needs.

Probably the fastest way would be to use

Arrays.asList(arr).subList(i, j);

This will be quick, because no elements are copied anywhere, and no iteration is performed. Arrays.asList(arr) essentially creates a list which is a wrapper for the original array, and subList(...) creates a list which is a view of the existing list.

The trade-off (there is always a trade-off) is that this retains a reference to the original array. So if you were generating a large number of large arrays, and wanted to keep a small slice of each one, this would be a poor choice from a memory-consumption perspective. (Conversely, if you had one large array, and wanted a large number of different slices of it, potentially overlapping, this would be a very memory-efficient approach as well as being fast.)

If memory considerations mean that you need to release any reference to the original array, then you are forced to copy elements to a new structure somehow. Probably the most efficient way to do this is to use the approach you suggested: Arrays.copyOfRange(...) basically delegates to System.arrayCopy(...), which is essentially implemented natively on most systems (bulk copy of a contiguous chunk of memory), and then as before Arrays.asList(...) just creates a list wrapper for that new array. So in the scenario that you want to release the reference to the original array, your suggested

Arrays.asList(Arrays.copyOfRange(arr, i, j));

is probably the "best" approach.

like image 123
James_D Avatar answered Jan 17 '23 15:01

James_D