Java随机shuffle列表,包含两个使用Collections.shuffle的元素

时间:2015-06-04 08:05:58

标签: java random collections

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class ShuffleList {
  public static void main(String[] args) {
    String [] file = {"1","2"};
    long seed = 3;
    ArrayList<String> fileList = new ArrayList<String>(Arrays.asList(file));
    for (int i=0; i<200; i++) {
      Collections.shuffle(fileList, new Random(seed));
      seed = seed +1;
      System.out.println(seed + "," + fileList);
    }
  }
}

输出是200行[1,2],而不是随机随机播放。事实上,对于所有种子而言都是如此。 4000。 这是为什么?我尝试了3个元素的列表,种子从1到100使得列表看似随机。但是2个元素列表有什么问题?

3 个答案:

答案 0 :(得分:5)

问题不在于shuffle - 它与Random的种子很少。这是一个程序,展示了:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        int total = 0;
        for (int seed = 0; seed < 4000; seed++) {
            Random rng = new Random(seed);
            total += rng.nextInt(2);
        }
        System.out.println(total);
    }
}

期望大约2000的输出 - 大约一半的nextInt调用应该返回0,大约一半应该返回1.相反,它是4000 - 每< / em> call返回1.

使用种子[10000,13999],你得到240 - 所以大多数调用返回0而不是1。

使用种子[100000,103999]你得到3226 - 变得更好......

使用种子[1000000,1003999]你得到2105 - 好多了。

我对RNGs的数学知之甚少,不知道为什么会发生这种情况,但看起来java.util.Random对于小种子来说有点破碎。

答案 1 :(得分:2)

对于两个元素的列表,shuffle做的是将一个元素与随机位置交换:

    if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
        for (int i=size; i>1; i--)
            swap(list, i-1, rnd.nextInt(i));
    }

这是使用Random实例的地方(大小为2,因此只有一次迭代):

swap(list, 2-1, rnd.nextInt(2));

所以你所证明的是,对于3到203之间的种子,第一次调用rnd.nextInt(2)会返回1.如果你在所有测试中使用了随机种子或使用相同的Random实例,你会得到一个不同的结果。

例如,将new Random(seed)更改为new Random(3)(实际上创建该实例一次并将其传递给Collections.shuffle会更有意义)会生成:

4,[1, 2]
5,[1, 2]
6,[2, 1]
7,[2, 1]
8,[1, 2]
9,[1, 2]
10,[1, 2]
11,[1, 2]
12,[2, 1]
13,[2, 1]
14,[2, 1]
15,[1, 2]
16,[1, 2]
17,[2, 1]
18,[1, 2]
19,[2, 1]
20,[2, 1]
21,[1, 2]
22,[1, 2]
23,[1, 2]
24,[2, 1]
25,[2, 1]
26,[2, 1]
27,[2, 1]
28,[2, 1]
29,[1, 2]
30,[1, 2]
31,[2, 1]
32,[2, 1]
33,[1, 2]
34,[2, 1]
35,[2, 1]
36,[2, 1]
37,[1, 2]
38,[2, 1]
39,[2, 1]
40,[1, 2]
41,[2, 1]
42,[1, 2]
43,[2, 1]
44,[1, 2]
45,[1, 2]
46,[2, 1]
47,[2, 1]
48,[1, 2]
49,[2, 1]
50,[2, 1]
51,[1, 2]
52,[1, 2]
53,[2, 1]
54,[2, 1]
55,[2, 1]
56,[2, 1]
57,[1, 2]
58,[2, 1]
59,[1, 2]
60,[1, 2]
61,[2, 1]
62,[2, 1]
63,[1, 2]
64,[2, 1]
65,[1, 2]
66,[2, 1]
67,[1, 2]
68,[2, 1]
69,[1, 2]
70,[2, 1]
71,[1, 2]
72,[1, 2]
73,[2, 1]
74,[1, 2]
75,[2, 1]
76,[1, 2]
77,[2, 1]
78,[1, 2]
79,[2, 1]
80,[1, 2]
81,[2, 1]
82,[2, 1]
83,[1, 2]
84,[1, 2]
85,[1, 2]
86,[2, 1]
87,[2, 1]
88,[1, 2]
89,[1, 2]
90,[2, 1]
91,[1, 2]
92,[1, 2]
93,[2, 1]
94,[1, 2]
95,[1, 2]
96,[1, 2]
97,[1, 2]
98,[1, 2]
99,[1, 2]
100,[1, 2]
101,[1, 2]
102,[2, 1]
103,[1, 2]
104,[2, 1]
105,[2, 1]
106,[1, 2]
107,[1, 2]
108,[1, 2]
109,[2, 1]
110,[2, 1]
111,[1, 2]
112,[2, 1]
113,[1, 2]
114,[1, 2]
115,[2, 1]
116,[2, 1]
117,[2, 1]
118,[1, 2]
119,[2, 1]
120,[1, 2]
121,[1, 2]
122,[1, 2]
123,[2, 1]
124,[1, 2]
125,[2, 1]
126,[1, 2]
127,[2, 1]
128,[2, 1]
129,[1, 2]
130,[1, 2]
131,[2, 1]
132,[2, 1]
133,[1, 2]
134,[1, 2]
135,[1, 2]
136,[2, 1]
137,[1, 2]
138,[2, 1]
139,[1, 2]
140,[2, 1]
141,[2, 1]
142,[1, 2]
143,[1, 2]
144,[2, 1]
145,[1, 2]
146,[1, 2]
147,[2, 1]
148,[2, 1]
149,[1, 2]
150,[2, 1]
151,[1, 2]
152,[1, 2]
153,[2, 1]
154,[2, 1]
155,[1, 2]
156,[2, 1]
157,[2, 1]
158,[2, 1]
159,[1, 2]
160,[1, 2]
161,[1, 2]
162,[1, 2]
163,[2, 1]
164,[2, 1]
165,[2, 1]
166,[1, 2]
167,[2, 1]
168,[2, 1]
169,[1, 2]
170,[2, 1]
171,[1, 2]
172,[2, 1]
173,[2, 1]
174,[1, 2]
175,[2, 1]
176,[1, 2]
177,[1, 2]
178,[2, 1]
179,[1, 2]
180,[2, 1]
181,[2, 1]
182,[1, 2]
183,[1, 2]
184,[2, 1]
185,[1, 2]
186,[2, 1]
187,[1, 2]
188,[2, 1]
189,[2, 1]
190,[2, 1]
191,[2, 1]
192,[2, 1]
193,[1, 2]
194,[2, 1]
195,[1, 2]
196,[2, 1]
197,[1, 2]
198,[2, 1]
199,[2, 1]
200,[2, 1]
201,[2, 1]
202,[2, 1]
203,[1, 2]

答案 2 :(得分:2)

为Jon和Eran +1。

如果你想让你的代码工作,不要每次通过循环实例化Random,在循环之前创建一个实例并将其传入.Random旨在以这种方式使用,而不是让种子在每次通话之前都改变了。

例如......

public class ShuffleList {
  public static void main(String[] args) {
    String [] file = {"1","2"};
    ArrayList<String> fileList = new ArrayList<String>(Arrays.asList(file));

    Random random = new Random(3);
    for (int i=0; i<200; i++) {
      Collections.shuffle(fileList, random);
      System.out.println(fileList);
    }
  }
}