Sepanjang Section ini kita memilih struktur, mengelola urutan, dan menjaga keunikan — namun banyak pekerjaan sehari-hari dengan collection justru berbentuk operasi satu kali: urutkan daftar ini, balik urutannya, hitung berapa kali satu nilai muncul, acak urutan kartu. Daripada menulis loop manual untuk setiap tugas itu, pustaka Java menyediakan dua class perkakas: Collections berisi puluhan static method yang bekerja pada collection apa pun, dan Arrays menjadi pasangannya untuk array mentah. Pada Chapter ini kita berkeliling method yang paling sering dipakai, membuktikan bahwa binarySearch punya aturan pakai yang keras, dan menunjukkan bahwa bahkan pengacakan pun bisa dibuat terulang secara presisi.
Class Collections sebagai Kotak Perkakas #
Seluruh method Collections adalah static method yang menerima collection sebagai argumen — tidak ada yang perlu di-new. Program berikut merangkai delapan operasi inti pada satu ArrayList<Integer> yang sama sehingga efek tiap operasi terlihat berurutan:
import java.util.*;
public class OperasiDasar {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(45, 12, 89, 33, 7));
System.out.println("awal : " + data);
Collections.sort(data);
System.out.println("sort : " + data);
Collections.reverse(data);
System.out.println("reverse : " + data);
Collections.swap(data, 0, 4);
System.out.println("swap(0, 4) : " + data);
Collections.replaceAll(data, 33, 30);
System.out.println("replaceAll : " + data);
Collections.addAll(data, 50, 60);
System.out.println("addAll : " + data);
List<Integer> pola = Collections.nCopies(3, 0);
System.out.println("nCopies(3, 0): " + pola);
Collections.fill(data, 0);
System.out.println("fill(0) : " + data);
}
}Output yang Dihasilkan:
awal : [45, 12, 89, 33, 7]
sort : [7, 12, 33, 45, 89]
reverse : [89, 45, 33, 12, 7]
swap(0, 4) : [7, 45, 33, 12, 89]
replaceAll : [7, 45, 30, 12, 89]
addAll : [7, 45, 30, 12, 89, 50, 60]
nCopies(3, 0): [0, 0, 0]
fill(0) : [0, 0, 0, 0, 0, 0, 0]Poin bedahnya:
- Baris 7-9 (
sortlalureverse):sortmenyusun menaik memakai urutan alami elemen (Integer.compare); untuk urutan lain,Collections.sort(data, comparator)menerimaComparatorsebagaimana dibahas pada Chapter Comparable dan Comparator.reversesekadar membalik posisi — jadisort+reverseadalah cara singkat memperoleh urutan menurun. - Baris 13-14 (
swapdanreplaceAll):swap(data, 0, 4)menukar dua posisi berdasarkan indeks, sedangkanreplaceAllmengganti setiap kemunculan nilai33dengan30— penggantian massal tanpa loop. - Baris 18-19 (
addAlldannCopies):addAllmenerima varargs sehingga beberapa elemen bisa masuk dalam satu panggilan;nCopies(3, 0)membuat list immutable berisi tiga elemen0— objek yang sama dirujuk tiga kali, murah untuk dipakai sebagai nilai pengisi awal. - Baris 23-24 (
fill): menimpa seluruh isi dengan satu nilai. Karenafillmengubah list di tempat, ia hanya menerima list mutable —Collections.fill(List.of(1, 2), 0)berakhir denganUnsupportedOperationException.
Statistik Cepat dan Pencarian Biner #
Kelompok kedua menjawab pertanyaan tanpa mengubah data: berapa frekuensi sebuah nilai, apakah dua collection saling lepas, di mana nilai terbesar dan terkecil, serta di posisi mana sebuah nilai berada pada list terurut:
import java.util.*;
public class StatistikDanPencarian {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(12, 7, 45, 12, 89, 7, 12));
System.out.println("frequency(12) : " + Collections.frequency(data, 12));
System.out.println("frequency(99) : " + Collections.frequency(data, 99));
List<Integer> hadiah = List.of(100, 200);
System.out.println("disjoint : " + Collections.disjoint(data, hadiah));
System.out.println("max : " + Collections.max(data));
System.out.println("min : " + Collections.min(data));
System.out.println("max (reverse) : " + Collections.max(data, Comparator.reverseOrder()));
List<String> nama = List.of("Budi", "Siti", "Dewi", "Anton");
System.out.println("max nama : " + Collections.max(nama));
System.out.println("min nama : " + Collections.min(nama));
// binarySearch menuntut list yang sudah terurut menaik.
List<Integer> terurut = new ArrayList<>(data);
Collections.sort(terurut);
System.out.println("terurut : " + terurut);
System.out.println("cari 45 : " + Collections.binarySearch(terurut, 45));
System.out.println("cari 20 : " + Collections.binarySearch(terurut, 20));
}
}Output yang Dihasilkan:
frequency(12) : 3
frequency(99) : 0
disjoint : true
max : 89
min : 7
max (reverse) : 7
max nama : Siti
min nama : Anton
terurut : [7, 7, 12, 12, 12, 45, 89]
cari 45 : 5
cari 20 : -6Poin bedahnya:
- Baris 8-9 (
frequency): menghitung kemunculan12menghasilkan3— pekerjaan yang manual menuntut satu loop penuh, di sini menjadi satu panggilan. - Baris 12 (
disjoint): mengembalikantruekarena tidak ada elemen yang sama antaradatadanhadiah— berguna untuk memeriksa dua kelompok yang seharusnya tidak saling bersinggungan;falseberarti ada minimal satu elemen bersama. - Baris 14-17 (
max/min): tanpaComparator, keduanya memakai urutan alami; varian dua argumen menerimaComparator—max(data, Comparator.reverseOrder())menghasilkan7, membuktikan bahwa “terbesar” mengikuti definisi urutan yang kita pasang.max/minjuga bekerja padaCollectionapa pun, bukan hanyaList. - Baris 25-27 (
binarySearch): pencarian biner membelah wilayah pencarian menjadi dua pada setiap langkah sehingga berbiaya O(log n). Menemukan45menghasilkan indeks5; tidak menemukan20menghasilkan-6— bukan sekadarfalse. Angka negatif itu adalah kode:-(titikSisip) - 1, sehingga-6berarti20akan disisipkan pada indeks5(di antara12dan45) bila kita ingin memasukkannya sambil menjaga list tetap terurut.
Acak yang Terkendali #
Collections.shuffle(list) mengacak urutan dengan sumber acak bawaan. Panggilan yang sama dengan argumen kedua — objek Random ber-seed tetap — menghasilkan pengacakan yang selalu identik, karena algoritma java.util.Random ditetapkan dalam spesifikasi Java sehingga seed yang sama menghasilkan deretan angka yang sama di semua JVM:
import java.util.*;
public class AcakTerkendali {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8));
Collections.shuffle(data, new Random(42));
System.out.println("shuffle seed 42 (pertama): " + data);
List<Integer> salinan = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8));
Collections.shuffle(salinan, new Random(42));
System.out.println("shuffle seed 42 (ulang) : " + salinan);
Collections.shuffle(data, new Random(7));
System.out.println("shuffle seed 7 : " + data);
}
}Output yang Dihasilkan:
shuffle seed 42 (pertama): [3, 7, 4, 2, 5, 1, 8, 6]
shuffle seed 42 (ulang) : [3, 7, 4, 2, 5, 1, 8, 6]
shuffle seed 7 : [3, 4, 8, 7, 5, 2, 6, 1]Poin bedahnya:
- Baris 7-8 dan 11-12 (dua seed 42): dua list berisi sama diacak dengan
new Random(42)yang masing-masing baru dibuat — hasilnya persis identik[3, 7, 4, 2, 5, 1, 8, 6]. Inilah determinisme yang membuat pengacakan bisa diuji. - Baris 14-15 (seed 7): seed berbeda menghasilkan pengacakan berbeda pada list yang sama. Seed adalah “kunci” seluruh deretan angka acak yang menyusulnya.
- Keterbatasan struktural:
shufflememindahkan elemen di tempat, sehingga list immutable sepertiList.of(...)akan menolaknya; salin dulu keArrayListsebagaimana dicontohkan.
Saudara Dekat: Class Arrays #
Class Arrays memainkan peran yang sama untuk array mentah: Arrays.sort mengurutkan, Arrays.toString mencetak isi, dan Arrays.asList menjembatani array ke dunia collection:
int[] angka = {45, 12, 89};
Arrays.sort(angka);
System.out.println(Arrays.toString(angka));
List<String> jembatan = Arrays.asList("Budi", "Siti");
jembatan.set(0, "Anton"); // boleh: penggantian elemen didukung
jembatan.add("Dewi"); // ditolak: ukuran tetapOutput yang Dihasilkan:
[12, 45, 89]
[Budi, Siti]
[Anton, Siti]
add ditolak: java.lang.UnsupportedOperationExceptionHasil Arrays.asList adalah list berukuran tetap yang menempel pada sumbernya — set mengubah elemen, tetapi add dan remove ditolak karena menambah atau mengurangi elemen berarti mengubah ukuran array yang tidak bisa bertumbuh. Untuk list yang bebas berubah, salin lewat new ArrayList<>(Arrays.asList(...)).
Perkakas Collections dan Arrays menuntaskan kotak alat pengelolaan isi. Pertanyaan penutup Section ini bersifat arsitektural: dari belasan struktur yang kini kita kenal — ArrayList, HashSet, TreeMap, ArrayDeque, PriorityQueue — mana yang seharusnya dipilih untuk sebuah kebutuhan data tertentu? Chapter berikutnya menyusun kerangka berpikirnya dalam bentuk pohon keputusan.
Referensi #
- Java API Specification: java.util.Collections
- Java API Specification: java.util.Arrays
- Dev.java: The Java Collections Framework
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
AcakTerkendali.java
Unduh berkasimport java.util.*;
public class AcakTerkendali {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8));
Collections.shuffle(data, new Random(42));
System.out.println("shuffle seed 42 (pertama): " + data);
List<Integer> salinan = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8));
Collections.shuffle(salinan, new Random(42));
System.out.println("shuffle seed 42 (ulang) : " + salinan);
Collections.shuffle(data, new Random(7));
System.out.println("shuffle seed 7 : " + data);
}
}
OperasiDasar.java
Unduh berkasimport java.util.*;
public class OperasiDasar {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(45, 12, 89, 33, 7));
System.out.println("awal : " + data);
Collections.sort(data);
System.out.println("sort : " + data);
Collections.reverse(data);
System.out.println("reverse : " + data);
Collections.swap(data, 0, 4);
System.out.println("swap(0, 4) : " + data);
Collections.replaceAll(data, 33, 30);
System.out.println("replaceAll : " + data);
Collections.addAll(data, 50, 60);
System.out.println("addAll : " + data);
List<Integer> pola = Collections.nCopies(3, 0);
System.out.println("nCopies(3, 0): " + pola);
Collections.fill(data, 0);
System.out.println("fill(0) : " + data);
}
}
StatistikDanPencarian.java
Unduh berkasimport java.util.*;
public class StatistikDanPencarian {
public static void main(String[] args) {
List<Integer> data = new ArrayList<>(List.of(12, 7, 45, 12, 89, 7, 12));
System.out.println("frequency(12) : " + Collections.frequency(data, 12));
System.out.println("frequency(99) : " + Collections.frequency(data, 99));
List<Integer> hadiah = List.of(100, 200);
System.out.println("disjoint : " + Collections.disjoint(data, hadiah));
System.out.println("max : " + Collections.max(data));
System.out.println("min : " + Collections.min(data));
System.out.println("max (reverse) : " + Collections.max(data, Comparator.reverseOrder()));
List<String> nama = List.of("Budi", "Siti", "Dewi", "Anton");
System.out.println("max nama : " + Collections.max(nama));
System.out.println("min nama : " + Collections.min(nama));
// binarySearch menuntut list yang sudah terurut menaik.
List<Integer> terurut = new ArrayList<>(data);
Collections.sort(terurut);
System.out.println("terurut : " + terurut);
System.out.println("cari 45 : " + Collections.binarySearch(terurut, 45));
System.out.println("cari 20 : " + Collections.binarySearch(terurut, 20));
}
}