FisherYates shuffle 基本思想(Knuth shuffle ):
打亂包含 n 個元素的陣列 a(索引 0..n-1):
對於 i 從 n − 1 降到 1 做
j ← 0 ≤ j ≤ i 的隨機整數
交換 a[j] 和 a[i]
JDK來源程式碼如下:
/**
* 將清單中的每個元素移動到清單中的隨機新位置
* 使用指定的隨機數產生器。
*
* @參數列表
* 待洗牌的列表
* @參數隨機
* 隨機數字產生器
*
* @拋出不支援的操作異常
* 不支援替換清單中的元素時
*/
@SuppressWarnings(“未選取”)
公共靜態無效洗牌(列表<?>列表,隨機隨機){
if (!(隨機存取的列表實例)) {
Object[] 數組 = list.toArray();
for (int i = array.length - 1; i > 0; i--) {
int索引 = random.nextInt(i + 1);
如果(索引 < 0){
索引=-索引;
}
物件溫度=數組[i];
數組[i] = 數組[索引];
數組[索引] = 暫時;
}
整數 i = 0;
ListIterator<Object> it = (ListIterator<Object>) 列表
.listIterator();
while (it.hasNext()) {
it.next();
it.set(數組[i++]);
}
} 別的 {
List<物件> rawList = (List<物件>) 列表;
for (int i = rawList.size() - 1; i > 0; i--) {
int索引 = random.nextInt(i + 1);
如果(索引 < 0){
索引=-索引;
}
rawList.set(index, rawList.set(i, rawList.get(index)));
}
}
}
公共靜態無效主(最終字串參數[]){
物件更改溫度;
List<Integer> numList = new ArrayList<Integer>();
List<Integer> firstList = new ArrayList<Integer>();
List<Integer> SecondList = new ArrayList<Integer>();
List<Integer>thirdList = new ArrayList<Integer>();
List<Integer> FourthList = new ArrayList<Integer>();
for (int i = 1; i <= 100000; i++) {
numList.add(i);
第一個列表.add(i);
第二個列表.add(i);
thirdList.add(i);
FourthList.add(i);
}
// 第一次隨機播放,使用changeTemp
getStartTime();
int randInt = 0;
for (int i = 0, length = firstList.size(); i < length; i++) {
randInt = getRandom(i,firstList.size());
更改溫度=firstList.get(i);
firstList.set(i,firstList.get(randInt));
firstList.set(randInt, javaShuffle.temp);
}
getEndTime("第一次隨機播放時間");
// 第二次洗牌,交換列表
getStartTime();
for (int i = 0, length = secondaryList.size(); i < length; i++) {
randInt = getRandom(i, secondaryList.size());
secondaryList.set(i, secondaryList.set(randInt, secondaryList.get(i)));
}
getEndTime("第二次洗牌運行時間");
// 第三次洗牌,更改產生隨機整數
getStartTime();
Object[] tempArray =thirdList.toArray();
隨機蘭特 = new Random();
整數 j = 0;
for (int i = tempArray.length - 1; i > 0; i--) {
j = rand.nextInt(i + 1);
thirdList.set(i,thirdList.set(j,thirdList.get(i)));
}
getEndTime("第三次洗牌運行時間");
// 第四次shuffle,模擬java shuffle
getStartTime();
隨機隨機 = new Random();
if (!(RandomAccess 的第四個清單實例)) {
Object[] array = FourthList.toArray();
for (int i = array.length - 1; i > 0; i--) {
int索引 = random.nextInt(i + 1);
如果(索引 < 0){
索引=-索引;
}
物件溫度=數組[i];
數組[i] = 數組[索引];
數組[索引] = 暫時;
}
整數 i = 0;
ListIterator<Integer> it = (ListIterator<Integer>) FourthList.listIterator();
while (it.hasNext()) {
it.next();
it.set((整數)數組[i++]);
}
} 別的 {
List<Integer> rawList = (List<Integer>) FourthList;
for (int i = rawList.size() - 1; i > 0; i--) {
int索引 = random.nextInt(i + 1);
如果(索引 < 0){
索引=-索引;
}
rawList.set(index, rawList.set(i, rawList.get(index)));
}
}
getEndTime("第四次shuffle運行時間");
// java 隨機播放
getStartTime();
收藏.shuffle(numList);
getEndTime("java shuffle 運行時間");
}
公共靜態無效交換(int a,int b){
javaShuffle.temp = a;
a = b;
b = javaShuffle.temp;
}
公共靜態 int getRandom(最終 int 低,最終 int 高){
return (int) (Math.random() * (高 - 低) + 低);
}
公共靜態無效 getStartTime() {
javaShuffle.start = System.nanoTime();
}
公共靜態無效 getEndTime(最終字串 s) {
javaShuffle.end = System.nanoTime();
System.out.println(s + ": " + (javaShuffle.end - javaShuffle.start) + "ns");
}
}
如果數值較小,例如100000級別,則輸出大概是:
第一次隨機播放運行時間:85029499ns
第二次隨機播放運行時間:80909474ns
第三次隨機播放運行時間:71543926ns
第四次隨機播放運行時間:76520595ns
java shuffle 運行時間:61027643ns
第一次隨機播放運行時間:82326239ns
第二次隨機播放運行時間:78575611ns
第三次隨機播放運行時間:95009632ns
第四次隨機播放運行時間:105946897ns
java shuffle 運行時間:90849302ns
第一次隨機播放運行時間:84539840ns
第二次隨機播放運行時間:85965575ns
第三次隨機播放運行時間:101814998ns
第四次隨機播放運行時間:113309672ns
java shuffle 運行時間:35089693ns
第一次隨機播放運行時間:87679863ns
第二次隨機播放運行時間:79991814ns
第三次隨機播放運行時間:73720515ns
第四次隨機播放運行時間:78353061ns
java shuffle 運行時間:64146465ns
第一次隨機播放運行時間:84314386ns
第二次隨機播放運行時間:80074803ns
第三次隨機播放運行時間:74001283ns
第四次隨機播放運行時間:79931321ns
java shuffle 運行時間:86427540ns
第一次隨機播放運行時間:84315523ns
第二次隨機播放運行時間:81468386ns
第三次隨機播放運行時間:75052284ns
第四次隨機播放運行時間:79461407ns
java shuffle 運行時間:66607729ns
如果是10000000級,大概如下:
第一次隨機播放運行時間:2115703288ns
第二次隨機播放運行時間:3114045871ns
第三次隨機播放運行時間:4664426798ns
第四次隨機播放運行時間:2962686695ns
java shuffle 運行時間:3246883026ns 第一次 shuffle 運行時間:2165398466ns
第二次隨機播放運行時間:3129558913ns
第三次隨機播放運行時間:4147859664ns
第四次隨機播放運行時間:2911849942ns
java shuffle 運行時間:4311703487ns 第一次 shuffle 運行時間:2227462247ns
第二次隨機播放運行時間:3279548770ns
第三次隨機播放運行時間:4704344954ns
第四次隨機播放運行時間:2942635980ns
java shuffle 運行時間:3933172427ns 第一次 shuffle 運行時間:2200158789ns
第二次隨機播放運行時間:3172666791ns
第三次隨機播放運行時間:4715631517ns
第四次隨機播放運行時間:2950817535ns
java shuffle 運行時間:3387417676ns 第一次 shuffle 運行時間:2201124449ns
第二次隨機播放運行時間:3203823874ns
第三次隨機播放運行時間:4179926278ns
第四次隨機播放運行時間:2913690411ns
java shuffle 運行時間:3571313813ns 第一次 shuffle 運行時間:2163053190ns
第二次隨機播放運行時間:3073889926ns
第三次隨機播放運行時間:4493831518ns
第四次隨機播放運行時間:2852713887ns
java shuffle運行時間:3773602415ns
可以看出,第一種方法速度最快,而第四種最慢。
在進行大數據處理的時候,如果使用java函式庫效率較低時,可以考慮使用其他方式。