如何在不使用Collections.shuffle的情况下获取Java中列表的随机子集?

时间:2011-08-05 20:27:51

标签: java collections

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

我想获得10,20,34,56(用户选择的任何大小部分)的子集,这个子集必须是随机选择的,我不能有重复。

Collections.shuffle()是否足以支持POJO的大型列表?或者有更有效/更安全的方式吗?

以我的例子为例,如果myStrings中有5万个字符串,如果你只想要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));
        }
    }
}

3 个答案:

答案 0 :(得分:4)

如果你想要的东西要小得多,那么洗牌整个清单会浪费一些资源。我个人只是在0..size之间选择n个唯一的随机数,并使用这些索引处的对象作为随机子集。

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

答案 1 :(得分:4)

如果您想要的项目数量远远少于集合的大小,那么只需随意绘制它们:

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));
}

答案 2 :(得分:1)

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