Pengacakan FisherYates 基本思想(Pengacakan Knuth ):
Untuk mengacak array a dari n elemen (indeks 0..n-1):
untuk saya dari n − 1 hingga 1 lakukan
j ← bilangan bulat acak dengan 0 ≤ j ≤ i
pertukaran a[j] dan a[i]
JDK memiliki fitur-fitur berikut:
/**
* Memindahkan setiap elemen Daftar ke posisi baru secara acak dalam daftar
* menggunakan generator nomor acak yang ditentukan.
*
* @daftar param
* Daftar yang akan diacak
* @param acak
* generator nomor acak
*
* @melemparkan UnsupportedOperationException
* ketika mengganti elemen dalam Daftar tidak didukung
*/
@SuppressWarnings("tidak dicentang")
public static void shuffle(Daftar<?> daftar, Acak acak) {
if (!(daftar instance dari RandomAccess)) {
Objek[] array = daftar.toArray();
for (int i = array.panjang - 1; i > 0; i--) {
int indeks = acak.nextInt(i + 1);
jika (indeks < 0) {
indeks = -indeks;
}
Suhu objek = array[i];
larik[i] = larik[indeks];
susunan[indeks] = suhu;
}
ke dalam saya = 0;
ListIterator<Object> it = (ListIterator<Object>) daftar
.listIterator();
sementara (itu.hasNext()) {
itu.berikutnya();
itu.set(array[i++]);
}
} kalau tidak {
Daftar<Objek> rawList = (Daftar<Objek>) daftar;
untuk (int i = rawList.size() - 1; i > 0; i--) {
int indeks = acak.nextInt(i + 1);
jika (indeks < 0) {
indeks = -indeks;
}
rawList.set(indeks, rawList.set(i, rawList.get(index)));
}
}
}
public static void main(String akhir args[]) {
Perubahan objekTemp;
Daftar<Bilangan Bulat> numList = Daftar Array baru<Bilangan Bulat>();
Daftar<Bilangan Bulat> Daftar Pertama = Daftar Array baru<Bilangan Bulat>();
Daftar<Bilangan Bulat> Daftar kedua = Daftar Array baru<Bilangan Bulat>();
Daftar<Bilangan Bulat> Daftar ketiga = Daftar Array baru<Bilangan Bulat>();
Daftar<Bilangan Bulat> Daftar keempat = Daftar Array baru<Bilangan Bulat>();
untuk (int saya = 1; saya <= 100000; saya++) {
numList.tambahkan(i);
FirstList.tambahkan(i);
Daftarkedua.tambahkan(i);
Daftar Ketiga.tambahkan(i);
Daftar keempat.tambahkan(i);
}
// kocok pertama, gunakan changeTemp
getStartTime();
int randInt = 0;
for (int i = 0, panjang = firstList.size(); i < panjang; i++) {
randInt = getRandom(i, firstList.size());
changeTemp = firstList.get(i);
FirstList.set(i, firstList.get(randInt));
firstList.set(randInt, javaShuffle.temp);
}
getEndTime("waktu pengacakan pertama");
// pengacakan kedua, daftar pertukaran
getStartTime();
for (int i = 0, panjang = secondList.size(); i < panjang; i++) {
randInt = getRandom(i, secondList.size());
secondList.set(i, secondList.set(randInt, secondList.get(i)));
}
getEndTime("waktu pengocokan kedua");
// pengacakan ketiga, ubah menghasilkan int acak
getStartTime();
Objek[] tempArray = thirdList.toArray();
Rand acak = acak baru();
ke dalam 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("waktu pengocokan ketiga");
// pengacakan keempat, simulasi pengacakan java
getStartTime();
Acak acak = baru Acak();
if (!(daftar keempat instance dari RandomAccess)) {
Objek[] array = Daftar keempat.toArray();
for (int i = array.panjang - 1; i > 0; i--) {
int indeks = acak.nextInt(i + 1);
jika (indeks < 0) {
indeks = -indeks;
}
Suhu objek = array[i];
larik[i] = larik[indeks];
susunan[indeks] = suhu;
}
ke dalam saya = 0;
ListIterator<Integer> it = (ListIterator<Integer>) FourthList.listIterator();
sementara (itu.hasNext()) {
itu.berikutnya();
itu.set((Bilangan Bulat) array[i++]);
}
} kalau tidak {
Daftar<Bilangan Bulat> Daftar mentah = (Daftar<Bilangan Bulat>) Daftar keempat;
untuk (int i = rawList.size() - 1; i > 0; i--) {
int indeks = acak.nextInt(i + 1);
jika (indeks < 0) {
indeks = -indeks;
}
rawList.set(indeks, rawList.set(i, rawList.get(index)));
}
}
getEndTime("waktu pengocokan keempat");
// java acak
getStartTime();
Koleksi.shuffle(numList);
getEndTime("waktu berjalan pengacakan java");
}
pertukaran kekosongan statis publik(int a, int b) {
javaShuffle.temp = a;
a = b;
b = javaShuffle.temp;
}
public static int getRandom(int akhir rendah, int akhir tinggi) {
return (int) (Math.random() * (tinggi - rendah) + rendah);
}
public static void getStartTime() {
javaShuffle.start = Sistem.nanoTime();
}
public static void getEndTime(String akhir) {
javaShuffle.end = Sistem.nanoTime();
System.out.println(s + ": " + (javaShuffle.end - javaShuffle.start) + "ns");
}
}
如果数值较小,例如100000级别,则输出大概是:
waktu pengocokan pertama: 85029499ns
waktu pengocokan kedua: 80909474ns
waktu pengocokan ketiga : 71543926ns
waktu pengocokan keempat: 76520595ns
waktu berjalan acak java: 61027643ns
waktu pengocokan pertama : 82326239ns
waktu pengocokan kedua: 78575611ns
waktu pengocokan ketiga : 95009632ns
waktu pengocokan keempat: 105946897ns
waktu berjalan acak java: 90849302ns
waktu pengocokan pertama: 84539840ns
waktu pengocokan kedua: 85965575ns
waktu pengocokan ketiga : 101814998ns
waktu pengocokan keempat: 113309672ns
waktu berjalan acak java: 35089693ns
waktu pengocokan pertama : 87679863ns
waktu pengocokan kedua: 79991814ns
waktu pengocokan ketiga : 73720515ns
waktu pengocokan keempat: 78353061ns
waktu berjalan acak java: 64146465ns
waktu pengocokan pertama: 84314386ns
waktu pengocokan kedua: 80074803ns
waktu pengocokan ketiga: 74001283ns
waktu pengocokan keempat: 79931321ns
waktu berjalan acak java: 86427540ns
waktu pengocokan pertama : 84315523ns
waktu pengocokan kedua: 81468386ns
waktu pengocokan ketiga : 75052284ns
waktu pengocokan keempat: 79461407ns
waktu berjalan acak java: 66607729ns
如果是10000000级别,大概如下:
waktu pengocokan pertama : 2115703288ns
waktu pengocokan kedua: 3114045871ns
waktu pengocokan ketiga : 4664426798ns
waktu pengocokan keempat: 2962686695ns
waktu proses acak java : 3246883026ns waktu proses acak pertama : 2165398466ns
waktu pengocokan kedua: 3129558913ns
waktu pengocokan ketiga : 4147859664ns
waktu pengocokan keempat: 2911849942ns
waktu proses acak java : 4311703487ns waktu proses acak pertama : 2227462247ns
waktu pengocokan kedua: 3279548770ns
waktu pengocokan ketiga : 4704344954ns
waktu pengocokan keempat: 2942635980ns
waktu proses acak java : 3933172427ns waktu proses acak pertama : 2200158789ns
waktu pengocokan kedua: 3172666791ns
waktu pengocokan ketiga : 4715631517ns
waktu pengocokan keempat: 2950817535ns
waktu proses acak java : 3387417676ns waktu proses acak pertama : 2201124449ns
waktu pengocokan kedua: 3203823874ns
waktu pengocokan ketiga : 4179926278ns
waktu pengocokan keempat: 2913690411ns
waktu proses acak java : 3571313813ns waktu proses acak pertama : 2163053190ns
waktu pengocokan kedua: 3073889926ns
waktu pengocokan ketiga : 4493831518ns
waktu pengocokan keempat: 2852713887ns
waktu berjalan acak java: 3773602415ns
可以看出,第一种方法速度最快,而第四种最慢。java自带 shuffle速度也不理想。
在进行大数据处理的时候,如果使用java库效率较低时,可以考虑使用其他方式。