我不理解在shuffle方法中使用额外的随机数。从我目前看到的例子来看,它没有任何好处,或者说有好处吗?它说它指定了随机性的来源,然而,洗牌方法本身不是随机的吗?那么,我为什么要进一步详细说明呢?
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//What is the difference?
Collection.shuffle(list);
Collection.shuffle(list, new Random(2));
您可能想要提供一个非默认随机性来源的两大原因:
- 再现性;以及
- 以使用更好的伪随机数生成器(PRNG)
#1——shuffle()
用于执行混洗的值序列,以及结果的顺序,取决于调用混洗方法时生成器的状态。如果您克隆您的列表,并在原始列表上调用shuffle()
,然后在其克隆上使用默认PRNG,您将获得两个不同的结果。同样,如果你或其他人多次运行你的程序,每次运行都会导致不同的洗牌,因为PRNG种子会不同。结果的可重复性对于调试以及允许同事在研究中验证您的结果至关重要。为了实现再现性,将具有固定种子的Random
对象传递给shuffle()
。
#2-Java对Random
的实现是一个48位的线性同余生成器。不错,但也不太好。如果您希望使用第三方生成器,如WELL或xoroshiro上的变体,可以通过使用所需的备用PRNG调用shuffle()
来实现。
随机参数指定随机性的来源
如果你创建了两个具有相同种子的随机对象,那么使用这些对象洗牌2个列表,如下所示:
Random R1 = new Random(1);
Random R2 = new Random(1); //Same seeds
Collections.shuffle(List1, R1);
Collections.shuffle(List2, R2);
然后,这两个列表将按照相同的顺序进行洗牌。如果列表相同,则结果也将相同。
如果你出于某种原因需要随机生成的东西是可复制的,这很有用。例如,在《我的世界》中,世界是随机生成的,但玩家可以共享生成世界的种子,这样其他人就可以生成完全相同的世界。