FisherYates Shuffle 基本思想 (Knuth Shuffle):
So mischen Sie ein Array a mit n Elementen (Indizes 0..n-1):
für i von n − 1 bis 1 do
j ← zufällige ganze Zahl mit 0 ≤ j ≤ i
tausche a[j] und a[i] aus
JDK-Version:
/**
* Verschiebt jedes Element der Liste an eine zufällige neue Position in der Liste
* unter Verwendung des angegebenen Zufallszahlengenerators.
*
* @param-Liste
* die Liste zum Mischen
* @param zufällig
* der Zufallszahlengenerator
*
* @throws UnsupportedOperationException
* beim Ersetzen eines Elements in der Liste wird nicht unterstützt
*/
@SuppressWarnings("ungeprüft")
public static void shuffle(List<?> list, Random random) {
if (!(list instanceof RandomAccess)) {
Object[] array = list.toArray();
for (int i = array.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
if (index < 0) {
index = -index;
}
Objekttemp = array[i];
array[i] = array[index];
array[index] = temp;
}
int i = 0;
ListIterator<Object> it = (ListIterator<Object>) Liste
.listIterator();
while (it.hasNext()) {
it.next();
it.set(array[i++]);
}
} anders {
List<Object> rawList = (List<Object>) list;
for (int i = rawList.size() - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
if (index < 0) {
index = -index;
}
rawList.set(index, rawList.set(i, rawList.get(index)));
}
}
}
public static void main(final String args[]) {
Objekt changeTemp;
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);
firstList.add(i);
secondList.add(i);
ThirdList.add(i);
fourList.add(i);
}
// zuerst mischen, changeTemp verwenden
getStartTime();
int randInt = 0;
for (int i = 0, length = firstList.size(); i < length; i++) {
randInt = getRandom(i, firstList.size());
changeTemp = firstList.get(i);
firstList.set(i, firstList.get(randInt));
firstList.set(randInt, javaShuffle.temp);
}
getEndTime("erste Shuffle-Laufzeit");
// zweites Mischen, Austauschliste
getStartTime();
for (int i = 0, length = secondList.size(); i < length; i++) {
randInt = getRandom(i, secondList.size());
secondList.set(i, secondList.set(randInt, secondList.get(i)));
}
getEndTime("zweite Shuffle-Laufzeit");
// drittes Mischen, Änderung, zufällige int generieren
getStartTime();
Object[] tempArray = ThirdList.toArray();
Zufälliger Rand = new Random();
int 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("dritte Shuffle-Laufzeit");
// Vierter Shuffle, Java Shuffle simulieren
getStartTime();
Zufällig random = new Random();
if (!(fourthList Instanz von RandomAccess)) {
Object[] array = fourList.toArray();
for (int i = array.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
if (index < 0) {
index = -index;
}
Objekttemp = array[i];
array[i] = array[index];
array[index] = temp;
}
int i = 0;
ListIterator<Integer> it = (ListIterator<Integer>) fourthList.listIterator();
while (it.hasNext()) {
it.next();
it.set((Integer) array[i++]);
}
} anders {
List<Integer> rawList = (List<Integer>) FourthList;
for (int i = rawList.size() - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
if (index < 0) {
index = -index;
}
rawList.set(index, rawList.set(i, rawList.get(index)));
}
}
getEndTime("vierte Shuffle-Laufzeit");
// Java Shuffle
getStartTime();
Collections.shuffle(numList);
getEndTime("Java Shuffle-Laufzeit");
}
public static void swap(int a, int b) {
javaShuffle.temp = a;
a = b;
b = javaShuffle.temp;
}
public static int getRandom(final int low, final int high) {
return (int) (Math.random() * (high - low) + low);
}
public static void getStartTime() {
javaShuffle.start = System.nanoTime();
}
public static void getEndTime(final String s) {
javaShuffle.end = System.nanoTime();
System.out.println(s + ": " + (javaShuffle.end - javaShuffle.start) + "ns");
}
}
如果数值较小, 例如100000级别, 则输出大概是:
Laufzeit des ersten Shuffle: 85029499 ns
zweite Shuffle-Laufzeit: 80909474 ns
Laufzeit des dritten Shuffle: 71543926 ns
Laufzeit des vierten Shuffle: 76520595 ns
Java Shuffle-Laufzeit: 61027643 ns
Laufzeit des ersten Shuffle: 82326239 ns
zweite Shuffle-Laufzeit: 78575611 ns
Laufzeit des dritten Shuffle: 95009632 ns
Laufzeit des vierten Shuffle: 105946897 ns
Java Shuffle-Laufzeit: 90849302 ns
Laufzeit des ersten Shuffle: 84539840 ns
zweite Shuffle-Laufzeit: 85965575 ns
Laufzeit des dritten Shuffle: 101814998 ns
Laufzeit des vierten Shuffle: 113309672 ns
Java Shuffle-Laufzeit: 35089693 ns
Laufzeit des ersten Shuffle: 87679863 ns
zweite Shuffle-Laufzeit: 79991814 ns
Laufzeit des dritten Shuffle: 73720515 ns
Laufzeit des vierten Shuffle: 78353061 ns
Laufzeit von Java Shuffle: 64146465 ns
Laufzeit des ersten Shuffle: 84314386 ns
zweite Shuffle-Laufzeit: 80074803 ns
Laufzeit des dritten Shuffle: 74001283 ns
Laufzeit des vierten Shuffle: 79931321 ns
Laufzeit von Java Shuffle: 86427540 ns
Laufzeit des ersten Shuffle: 84315523 ns
zweite Shuffle-Laufzeit: 81468386 ns
Laufzeit des dritten Shuffle: 75052284 ns
Laufzeit des vierten Shuffle: 79461407 ns
Laufzeit von Java Shuffle: 66607729 ns
如果是10000000级别, 大概如下:
Laufzeit des ersten Shuffle: 2115703288 ns
zweite Shuffle-Laufzeit: 3114045871 ns
Laufzeit des dritten Shuffle: 4664426798 ns
Laufzeit des vierten Shuffle: 2962686695 ns
Java Shuffle-Laufzeit: 3246883026 ns erste Shuffle-Laufzeit: 2165398466 ns
zweite Shuffle-Laufzeit: 3129558913 ns
Laufzeit des dritten Shuffle: 4147859664 ns
Laufzeit des vierten Shuffle: 2911849942 ns
Java Shuffle-Laufzeit: 4311703487 ns erste Shuffle-Laufzeit: 2227462247 ns
zweite Shuffle-Laufzeit: 3279548770 ns
Laufzeit des dritten Shuffle: 4704344954 ns
Laufzeit des vierten Shuffle: 2942635980 ns
Java Shuffle-Laufzeit: 3933172427 ns erste Shuffle-Laufzeit: 2200158789 ns
zweite Shuffle-Laufzeit: 3172666791 ns
Laufzeit des dritten Shuffle: 4715631517 ns
Laufzeit des vierten Shuffle: 2950817535 ns
Java Shuffle-Laufzeit: 3387417676 ns erste Shuffle-Laufzeit: 2201124449 ns
zweite Shuffle-Laufzeit: 3203823874 ns
Laufzeit des dritten Shuffle: 4179926278 ns
Laufzeit des vierten Shuffle: 2913690411 ns
Java Shuffle-Laufzeit: 3571313813 ns erste Shuffle-Laufzeit: 2163053190 ns
zweite Shuffle-Laufzeit: 3073889926 ns
Laufzeit des dritten Shuffle: 4493831518 ns
Laufzeit des vierten Shuffle: 2852713887 ns
Java Shuffle-Laufzeit: 3773602415 ns
可以看出,第一种方法速度最快,而第四种最慢.java自带 shuffle速度也不理想.
在进行大数据处理的时候, 如果使用java库效率较低时, 可以考虑使用其他方式.