First, as so eloquently answered by Basil Bourque, shuffling doesn't depend on the complexity of an object or even a primitive. Objects are stored as references which are in fact ints which "point" or "refer" to their location in memory. Since shuffling is simply moving objects around, you are simply moving their references.
But here is a relatively efficient way to do what you want.
This works equally well for all list sizes and types, is very efficient, and requires no shuffling of the entire list. The overall efficiency is based on the number of items to be removed. Duplicates will never appear unless there are duplicates in the source list.
It has the advantages of using what I refer to as a "partial shuffle
" to reposition the last element to the index of the one just selected and then removes the last element (per your stated requirement).
Generate the source list
List<Integer> listInts = new ArrayList<>(IntStream
.rangeClosed(1, 30).boxed().toList());
Now the algorithm
- iterate thru the removal count
- generate a random number within the list's range.
- add the
selected
item to the removed
list
- copy the last item in the
list
to the selected item's spot.
- then remove the last item (this is very fast since no internal repositioning of the list is required).
public static <T> List<T> getRandomSelections(List<T> sourceList, int sizeOfSublist) {
List<T> removed = new ArrayList<>();
Random r = new Random();
int size = sourceList.size();
for (int i = 0; i < sizeOfSublist; i++) {
int selection = r.nextInt(0, size);
removed.add(sourceList.get(selection));
sourceList.set(selection, sourceList.get(--size));
sourceList.remove(size);
}
return removed;
}
Demo
List<Integer> removedInts = getRandomSelections(listInts, 10);
System.out.println("removedInts: " + removed);
System.out.println("remainingInts: "+ list);
Now the removed
list contains the desired items and the original list
contains the remaining
items.
Here is one using words.
List<String> listWords = new ArrayList<>(List.of("to", "be", "or", "not",
"to", "be", "that", "is", "the", "question"));
List<String> removedWords = getRandomSelections(listWords, 5);
System.out.println("removedWords: " +removedWords);
System.out.println("remainingWords: " + listWords);
prints something like
removedInts: [19, 16, 26, 1, 12, 15, 5, 13, 21, 9]
remainingInts: [27, 2, 3, 4, 24, 6, 7, 8, 22, 10, 11, 28, 23, 14, 25, 29, 17, 18, 30, 20]
removedWords: [question, or, is, to, to]
remainingWords: [that, be, the, not, be]