从Java中的列表中选择多个随机元素

所以说我有

List teamList = new LinkedList() teamList.add("team1"); teamList.add("team2"); teamList.add("team3"); teamList.add("team4"); teamList.add("team5"); teamList.add("team6"); 

是否有一种简单的选择方法…以随机方式说明该列表中的6个元素中的3个而不选择相同的元素两次(或更多次)?

尝试这个:

 public static List pickNRandom(List lst, int n) { List copy = new LinkedList(lst); Collections.shuffle(copy); return copy.subList(0, n); } 

我假设输入列表中没有重复的元素,我也采取了预防措施来改变副本,使原始列表不受干扰。 它被称为这样:

 List randomPicks = pickNRandom(teamList, 3); 

创建一组整数,并将0和列表长度减去1之间的随机数放入循环中,而集合的大小不等于所需的随机元素数。 浏览集合,并选择集合中的数字所指示的列表元素。 这样可以保持原始列表的完整性。

shuffle方法是最惯用的:在此之后,第一个K元素正是您所需要的。

如果K远小于列表的长度,您可能希望更快。 在这种情况下,遍历列表,随机地将当前元素与其自身或其后的任何元素进行交换。 在第K个元素之后,停止并返回K前缀:它将已经完全洗牌,您不需要关心列表的其余部分。

(显然,你想在这里使用ArrayList

您也可以使用水库采样 。

它的优点是您不需要事先知道源列表的大小(例如,如果给您一个Iterable而不是List 。)即使源列表不是随机访问,它也是有效的,如您的示例中的LinkedList

使用

 Collections.shuffle(teamList); 

随机化列表,然后通过teamList.remove(0);从列表中一次删除一个团队teamList.remove(0);

例如:

  List teamList = new LinkedList(); teamList.add("team1"); teamList.add("team2"); teamList.add("team3"); teamList.add("team4"); teamList.add("team5"); teamList.add("team6"); java.util.Collections.shuffle(teamList); String[] chosen3 = new String[3]; for (int i = 0; i < chosen3.length && teamList.size() > 0; i++) { chosen3[i] = teamList.remove(0); } 

所有好的想法,但洗牌是昂贵的。 更有效的方法(IMO)将执行计数控制循环并在0和n之间选择随机int; 其中n最初等于列表的长度。

在循环的每次迭代中,将所选项目与列表中n-1的项目交换,并将n递减1。 这样,您可以避免两次选择相同的元素,而不必保留所选项目的单独列表。

以下是使用Java流进行此操作的方法,无需创建原始列表的副本或对其进行混洗:

 public static List pickRandom(List list, int n) { if (n > list.size()) { throw new IllegalArgumentException("not enough elements"); } Random random = new Random(); return IntStream .generate(() -> random.nextInt(list.size())) .distinct() .limit(n) .mapToObj(list::get) .collect(Collectors.toList()); } 

注意:当n与巨大列表的列表大小太接近时,它可能变得低效。

 int[] getRandoms(int[] ranges, int n, int[] excepts) { int min = ranges[0]; int max = ranges[1]; int[] results = new int[n]; for (int i = 0; i < n; i++) { int randomValue = new Random().nextInt(max - min + 1) + min; if (ArrayUtils.contains(results, randomValue) || ArrayUtils.contains(excepts, randomValue)) { i--; } else { results[i] = randomValue; } } return results; } 

util类

 public static class ArrayUtils { public static boolean contains(int[] array, int elem) { return getArrayIndex(array, elem) != -1; } /** Return the index of {@code needle} in the {@code array}, or else {@code -1} */ public static int getArrayIndex(int[] array, int needle) { if (array == null) { return -1; } for (int i = 0; i < array.length; ++i) { if (array[i] == needle) { return i; } } return -1; } } 

运用

 int[] randomPositions = getRandoms(new int[]{0,list.size()-1}, 3, new int[]{0,1}); 

除了第0项和第1项之外,它会随机列出3个项目