具有固定Random的随机播放列表不会返回相同的结果

Lis*_*aMM 0 java collections

我有一种方法,在某些时候洗牌List.重要的是我以后可以重现这个改组.为了实现这一点,我传递Random给后来传递给的方法Collection.shuffle(List, Random).我期望使用相同的Random和相同的列表将导致相同的混洗列表,但显然我遗漏了一些东西.

使用Strings代替我的对象的示例代码:

    @Test
    public final void shuffleTest() {
        Random random = new Random(555);

        List<String> text = new ArrayList<>();
        text.add("one");
        text.add("two");
        text.add("three");
        text.add("four");

        List<String> shuffled = shuffleList(new ArrayList<>(text), random);
        List<String> shuffled2 = shuffleList(new ArrayList<>(text), random);
        Assertions.assertThat(shuffled).isEqualTo(shuffled2);
    }

    private List<String> shuffleList(List<String> text, Random random) {
        Collections.shuffle(text, random);
        return text;
    }
Run Code Online (Sandbox Code Playgroud)

我确实注意到,如果不是通过它Random,我会传递种子,并且new Random(seed)每次它确实有效,但我想避免这种情况.

Nei*_*son 6

您自己提供了答案。初始化一个Random实例后,它会产生一个伪随机数序列。这个序列中的一些将被第一次 shuffle 消耗,因此第二次 shuffle 将使用序列的下一位。为了使用相同的序列,Random实例在每次洗牌之前必须处于相同的状态。具有相同种子的新实例符合要求。


And*_*ner 6

如果你这样做:

List<String> shuffled = shuffleList(new ArrayList<>(text), new Random(555));
List<String> shuffled2 = shuffleList(new ArrayList<>(text), new Random(555));
Run Code Online (Sandbox Code Playgroud)

他们确实是平等的.

但是,您使用相同的随机实例两次:在第一次shuffle之后,Random它处于与之前不同的状态,因此它将以不同方式对列表进行洗牌.