How to randomly select an item from a list in Java
In order to display random products or related links to a customer, it may be necessary to select one or more random items from a list.
Select a random item
Selecting a single random item is relatively easy. The elements of a list can be accessed directly via the index and the length is known:
import java.util.*; public class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); String name = names.get(new Random().nextInt(names.size())); System.out.println(name); } }
Output:
Amanda[st_adsense]
With this method it is noticeable that a new random object is created when the query is made. This is relatively expensive and if the code is called often, it pays off to outsource the code to a separate method.
private static Random random = new Random(); public static <T> T getRandomItem(List<T> list) { if(list.isEmpty()) { throw new IllegalArgumentException( "The list cannot be empty!"); } T item = list.get(random.nextInt(list.size())); return item; }
The random object is now stored in its own static variable. We don’t need to worry about synchronizing the variable in a concurrent scenario. However, the list must not be empty, otherwise we cannot return an element. In the case of an empty list, an IllegalArgumentException is thrown with an error message.
Select multiple random items
To select multiple random items, the above method getRandomItem() can easily be called multiple times.
//Not optimal! public static <T> List<T> getRandomItems(List<T> list, int count) { List<T> arr = new ArrayList<>(); for (int i = 0; i < count; i++) { arr.add(getRandomItem(list)); } return arr; }
The problem is that Random.nextInt() can of course return the same number several times and thus the getRandomItems() method could return duplicate items.
[st_adsense]
To prevent this, a different approach is taken. First the list is sorted randomly and then the first count elements are simply returned. Java offers a useful utility method for randomly sorting a list: Collections.shuffle().
public static <T> List<T> getRandomShuffledItems(List<T> list, int count) { if(list.isEmpty()) { throw new IllegalArgumentException("The list cannot be empty!"); } if(count > list.size()) { count = list.size(); } List<T> copy = new ArrayList<>(list); List<T> result = new ArrayList<>(); Collections.shuffle(copy); return copy.subList(0, count - 1); }
Note that Collections.shuffle() changes the list directly. Therefore a copy of the list is created which is then “shuffled”. Note that count can only be as large as the list has elements.
If you want to select multiple random elements, you have to take into account that entries in a list can appear twice. If you want to prevent that several identical elements are selected, you can convert the list into a set. A set contains by definition only different elements:
public static <T> List<T> getRandomDistinctItems(List<T> list, int count) { if(list.isEmpty()) { throw new IllegalArgumentException("The list cannot be empty!"); } List<T> copy = new ArrayList<>(new HashSet<>(list)); if(count > copy.size()) { count = copy.size(); } List<T> result = new ArrayList<>(); Collections.shuffle(copy); return copy.subList(0, count - 1); }[st_adsense]