簡體   English   中英

Java隨機shuffle列表,包含兩個使用Collections.shuffle的元素

[英]Java random shuffle list with two elements using Collections.shuffle

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個元素列表有什么問題?

問題不在於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 - 每個調用返回1。

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

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

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

我不太了解RNG的數學,以說明為什么會發生這種情況,但它看起來像java.util.Random有點像小種子。

對於兩個元素的列表,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]

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM