【问题标题】:How can you obtain a randomized subset of a list in Java, without using Collections.shuffle?在不使用 Collections.shuffle 的情况下,如何在 Java 中获取列表的随机子集?
【发布时间】:2011-08-05 20:27:51
【问题描述】:

我有一个 List 的对象,这个列表可能包含数千个元素。

我想获得其中的 10、20、34、56(无论用户选择什么大小的部分)子集,这个子集必须是随机选择的,我不能有重复。

Collections.shuffle() 对于大型 POJO 列表是否足够?还是有更有效/更安全的方法?

以我的例子为例,如果 myStrings 有 50,000 个字符串,如果您只需要 5 个项目,那么调用 Collections.shuffle() 是个好主意吗?

public class ShuffleMe
{

    public static void main(String[] args)
    {
        int NUM_OF_ELEMENTS_TO_PICK = 3;
        List<String> myStrings = new ArrayList<String>();

        myStrings.add("A");
        myStrings.add("B");
        myStrings.add("C");
        myStrings.add("D");
        myStrings.add("E");
        myStrings.add("F");

        Collections.shuffle(myStrings);

        for (int i = 0; i < NUM_OF_ELEMENTS_TO_PICK; i++)
        {
            System.out.println(myStrings.get(i));
        }
    }
}

【问题讨论】:

  • 您能否澄清一下,用户选择的是单个子集的大小,还是要生成的子集的数量?如果是后者,子集的大小应该是多少?
  • 我不想使用Collections.sort() 的原因是因为我不想从数据库调用中检索所有项目,如果我只实际使用其中的几个,这会改变任何答案吗?

标签: java collections


【解决方案1】:

如果您想要的内容明显更小,则将整个列表打乱会有点浪费资源。我个人只是选择 0..size 之间的 n 个唯一随机数,并将这些索引处的对象用于随机子集。

如果您要选择一个非常接近整个集合大小的随机子集,那么您最好只调用Collections.shuffle() 并选择第一个n 条目。但如果我们谈论的是 ~5 / 50,000,请务必使用上述方法。

【讨论】:

    【解决方案2】:

    如果你想要的item数量远小于集合的大小,就随机抽取吧:

    Set<Integer> randSubSet = new HashSet<Integer>();
    while(randSubSet.size() < NUM_OF_ELEMENTS_TO_PICK) {
        randSubSet.add((int)(Math.random()*myStrings.size()));
    }
    for (int i : randSubSet) {
        System.out.println(myStrings.get(i));
    }
    

    【讨论】:

      【解决方案3】:

      使用Fisher-Yates shuffle,但只运行足够远以选择您需要的元素数量。

      【讨论】:

        猜你喜欢
        • 2011-03-20
        • 1970-01-01
        • 1970-01-01
        • 2023-02-25
        • 2018-10-12
        • 2021-10-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多