«1. Введение

Выбор случайного элемента списка — очень простая операция, но не столь очевидная для реализации. В этой статье мы покажем наиболее эффективный способ сделать это в различных контекстах.

2. Выбор случайного элемента/элементов

Чтобы получить случайный элемент из экземпляра списка, вам необходимо сгенерировать случайный индексный номер, а затем получить элемент по этому сгенерированному индексному номеру с помощью List.get() метод.

Ключевым моментом здесь является то, что вы не должны использовать индекс, превышающий размер вашего списка.

2.1. Один случайный элемент

Чтобы выбрать случайный индекс, вы можете использовать метод Random.nextInt(intbound):

public void givenList_shouldReturnARandomElement() {
    List<Integer> givenList = Arrays.asList(1, 2, 3);
    Random rand = new Random();
    int randomElement = givenList.get(rand.nextInt(givenList.size()));
}

Вместо класса Random вы всегда можете использовать статический метод Math.random() и умножить это с размером списка (Math.random() генерирует двойное случайное значение между 0 (включительно) и 1 (исключительно), поэтому не забудьте привести его к int после умножения).

2.2. Выбор случайного индекса в многопоточной среде

При написании многопоточных приложений с использованием одного экземпляра класса Random может быть выбрано одно и то же значение для каждого процесса, обращающегося к этому экземпляру. Мы всегда можем создать новый экземпляр для каждого потока, используя выделенный класс ThreadLocalRandom:

int randomElementIndex
  = ThreadLocalRandom.current().nextInt(listSize) % givenList.size();

2.3. Выберите случайные элементы с повторениями

Иногда вам может понадобиться выбрать несколько элементов из списка. Это довольно просто:

public void givenList_whenNumberElementsChosen_shouldReturnRandomElementsRepeat() {
    Random rand = new Random();
    List<String> givenList = Arrays.asList("one", "two", "three", "four");

    int numberOfElements = 2;

    for (int i = 0; i < numberOfElements; i++) {
        int randomIndex = rand.nextInt(givenList.size());
        String randomElement = givenList.get(randomIndex);
    }
}

2.4. Выбрать случайные элементы без повторов

Здесь нужно убедиться, что элемент удаляется из списка после выбора:

public void givenList_whenNumberElementsChosen_shouldReturnRandomElementsNoRepeat() {
    Random rand = new Random();
    List<String> givenList = Lists.newArrayList("one", "two", "three", "four");

    int numberOfElements = 2;

    for (int i = 0; i < numberOfElements; i++) {
        int randomIndex = rand.nextInt(givenList.size());
        String randomElement = givenList.get(randomIndex);
        givenList.remove(randomIndex);
    }
}

2.5. Выбрать случайную серию

Если вы хотите получить случайную серию элементов, вам может пригодиться класс Collections utils:

public void givenList_whenSeriesLengthChosen_shouldReturnRandomSeries() {
    List<Integer> givenList = Lists.newArrayList(1, 2, 3, 4, 5, 6);
    Collections.shuffle(givenList);

    int randomSeriesLength = 3;

    List<Integer> randomSeries = givenList.subList(0, randomSeriesLength);
}

3. Заключение

В этой статье мы рассмотрели наиболее эффективный способ получения случайной выборки. элементы из экземпляра List для разных сценариев.

Примеры кода можно найти на GitHub.