在洗牌阵列时处理重复项

时间:2017-02-06 16:07:41

标签: java arrays collections shuffle

我希望将具有重复元素的数组洗牌。使用Collections中的shuffle方法,它如何处理重复项?我不希望两个副本相互交换。感谢

2 个答案:

答案 0 :(得分:0)

所有关于该方法行为的保证都在Javadoc中。

当前实现选择随机交换,而不考虑列表的内容。一般合同规定理想是所有排列都是同等可能的,所以我不会预期它会进入需要移动元素的实现,更不用说要求它与不同值的元素交换。一般来说,什么改组是 - 随机顺序,也可以(一些小的时间)意味着"相同的顺序(或等效的顺序) )&#34 ;. var label = (Label)ControlsCollection.Find("supName" + i,true); 方法解决了一般情况。

如果您需要使用不同值的元素交换每个元素,您当然可以编写自己的方法来执行此操作。请注意,如果相对于集合的大小有太多重复,那么天真的实现可能会陷入无限循环。

答案 1 :(得分:0)

这是Collections #shuffle(List,Random)的方法(可以找到包含文档的pastebin here

@SuppressWarnings({"rawtypes", "unchecked"})
public static void shuffle(List<?> list, Random rnd) {
    int size = list.size();
    if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
        for (int i=size; i>1; i--)
            swap(list, i-1, rnd.nextInt(i));
    } else {
        Object arr[] = list.toArray();

        // Shuffle array
        for (int i=size; i>1; i--)
            swap(arr, i-1, rnd.nextInt(i));

        // Dump array back into list
        // instead of using a raw type here, it's possible to capture
        // the wildcard but it will require a call to a supplementary
        // private method
        ListIterator it = list.listIterator();
        for (int i=0; i<arr.length; i++) {
            it.next();
            it.set(arr[i]);
        }
    }
}

这是Collections #shuffle(List)的重载变体。
不同之处在于,如果您想自己播种,可以传递自己的随机对象 正如您所看到的,它不会查看每个数组槽中的值。您可以尝试覆盖此方法并包括检查重复项。

旁注:尝试检查JavaDocs是否存在这类问题。如果您不确定方法是如何工作的,只需谷歌类+方法名称,或在您的计算机上使用本地Java源代码。