我的关注 |
¥0.1 Java 如何从List中随机出N条数据?如何从List中按照不同权重(概率)随机出N条数据?
0

Java 如何从List中随机出N条数据?
比如从[1,2,3,4,5,6] 等概率的随机出3条数据?
如何从List中按照不同权重(概率)随机出N条数据?
比如

  1. public class A {
  2. int value;
  3. int weight; // 权重
  4. public A(int value,int weight){
  5. this.value = value;
  6. this.weight = weight;
  7. }
  8. }
  1. List<A> list = new ArrayList<>();
  2. list.add(new A(1,1));
  3. list.add(new A(2,2));
  4. list.add(new A(3,3));
  5. list.add(new A(4,1));
  6. list.add(new A(5,2));
  7. list.add(new A(6,1));
  8. list.add(new A(7,3));
  9. list.add(new A(8,1));

A 有三种权重,分别为1,2,3,依据A的权重不同(概率不同),如何随机出N条元素?其中weight=3的元素出现的概率是weight=1的3倍,weight=2的元素出现的概率是weight=1的2倍。

1个回答
0
采纳

定义类:

  1. public class A {
  2. int value;
  3. int weight; // 权重
  4. public A(int value, int weight) {
  5. this.value = value;
  6. this.weight = weight;
  7. }
  8. @Override
  9. public String toString() {
  10. return value + "_" + weight;
  11. }
  12. }

对于列表

  1. List<A> list = new ArrayList<>();
  2. list.add(new A(1,1));
  3. list.add(new A(2,2));
  4. list.add(new A(3,3));
  5. list.add(new A(4,1));
  6. list.add(new A(5,2));
  7. list.add(new A(6,1));
  8. list.add(new A(7,3));
  9. list.add(new A(8,1));

等概率随机

有两种思路,

方法1

从列表中随机出1个元素,移除这个元素,然后继续随机并移除,直到移除出N个
示例:

  1. long start = System.currentTimeMillis();
  2. List<A> resultList = new ArrayList<>();
  3. Random random = new Random();
  4. int n = 3; // n条
  5. for (int i = 0; i < n; i++) {
  6. int index = random.nextInt(list.size());
  7. resultList.add(list.get(index));
  8. list.remove(index);
  9. }
  10. resultList.forEach(System.out::println);
  11. System.out.println("耗时:" + (System.currentTimeMillis() - start));

输出:

  1. 1_1
  2. 2_2
  3. 8_1
  4. 耗时:59
方法2 (推荐,代码更简单)

将列表随机排列,取列表前N个元素。
推荐原因:代码更简单,效率更高

  1. long start = System.currentTimeMillis();
  2. Collections.shuffle(list); // 打乱,随机排列
  3. int n = 3;
  4. List<A> resultList = list.subList(0, n);
  5. resultList.forEach(System.out::println);
  6. System.out.println("耗时:" + (System.currentTimeMillis() - start));

输出

  1. 3_3
  2. 7_3
  3. 2_2
  4. 耗时:57

非等概率随机

也有两种思路(权重为:1,2,3)

方法1.

第一步 按照权重不同,将List分成3个List. 分别为List1,List2,List3
第二步 从0~5随机出一个元素。如果随机值为0,则从List1中随机出一个元素并移除;如果随机值为1或2,则从List2中等概率随机出一个元素并移除;如果随机值是为3/4/5,则从List3中随机出一个元素并移除。直到随机出N个。
这个代码比较复杂,就不写了。

方法2 (推荐,代码更简单,效率高10倍)

第一步 将List扩充。

  1. long start = System.currentTimeMillis();
  2. List<A> newList = new ArrayList<>();
  3. for (A a : list) {
  4. for (int i = 0; i < a.weight; i++) {
  5. newList.add(a);
  6. }
  7. }

第二步 将newList随机排列,去重,取前N条

  1. Collections.shuffle(newList); // 随机排列
  2. int n = 3;
  3. List<A> resultList = newList.stream()
  4. .limit(n * 3) // 3为最大权重,取前N*3条
  5. .collect(Collectors.toSet()) // 使用set去重
  6. .stream()
  7. .limit(n) // 取前N条
  8. .collect(Collectors.toList());
  9. resultList.forEach(System.out::println); // 输出
  10. System.out.println("耗时:" + (System.currentTimeMillis() - start));

输出

  1. 7_3
  2. 3_3
  3. 3_3
  4. 耗时:61
采纳答案
麋鹿情人
修改
评论 (0)
撰写回答