Kelas Utilitas Arrays

Memanfaatkan sort, toString, copyOf, fill, dan binarySearch dari kelas java.util.Arrays.

Daftar isi

Operasi yang berulang pada array, seperti menampilkan isinya, mengurutkan, menyalin, mengisi, dan mencari, ternyata sudah disediakan oleh kelas java.util.Arrays. Kelas ini berisi metode static yang semuanya bekerja langsung terhadap array sebagai masukannya. Topik ini membahas lima metode yang paling sering dipakai, yaitu toString, sort, copyOf, fill, dan binarySearch, lengkap dengan syarat dan jebakan masing-masing.

Menampilkan isi array#

Mencetak variabel array langsung tidak menampilkan isinya. Keluaran yang muncul berupa nama tipe diikuti alamat objeknya, bukan daftar elemen.

java Contoh: mencetak array tanpa dan dengan Arrays.toString
// tidak-dijalankan
System.out.println(nilai);                  // [I@1b6d3586, alamat berubah-ubah
System.out.println(Arrays.toString(nilai)); // [80, 75, 90, 60]

Teks seperti [I@1b6d3586 adalah cara bawaan Java menampilkan objek, yaitu tipe [I untuk array int diikuti tanda @ dan kode hash identitas yang nilainya berbeda setiap kali program dijalankan. Kelas Arrays menyediakan toString yang menyusun isi array menjadi teks berformat [elemen, elemen, …]. Untuk array dua dimensi, tersedia deepToString yang menyusuri baris di dalamnya secara rekursif.

java TampilkanArray.java
import java.util.Arrays;

public class TampilkanArray {
    public static void main(String[] args) {
        int[] nilai = {80, 75, 90, 60};
        int[][] matriks = {{1, 2}, {3, 4}};

        System.out.println(Arrays.toString(nilai));
        System.out.println(Arrays.deepToString(matriks));
    }
}
text Keluaran
[80, 75, 90, 60]
[[1, 2], [3, 4]]

Metode toString hanya menyusun satu tingkat array, sehingga dipakai pada array dua dimensi akan menghasilkan teks seperti [I@…, [I@…] yang isinya alamat baris, bukan angka. Karena itu array bertingkat selalu memakai deepToString.

Mengurutkan dengan sort#

Arrays.sort mengurutkan elemen array menaik dan mengubah array itu langsung di tempatnya, bukan menghasilkan array baru. Setelah pemanggilan, urutan elemen lama hilang karena digantikan urutan baru.

java UrutkanNilai.java
import java.util.Arrays;

public class UrutkanNilai {
    public static void main(String[] args) {
        int[] nilai = {80, 75, 90, 60, 85};
        String[] nama = {"Dewi", "Ali", "Budi", "Citra"};

        Arrays.sort(nilai);
        Arrays.sort(nama);

        System.out.println(Arrays.toString(nilai));
        System.out.println(Arrays.toString(nama));
    }
}
text Keluaran
[60, 75, 80, 85, 90]
[Ali, Budi, Citra, Dewi]

Array angka terurut menaik berdasarkan nilainya, sedangkan array String terurut berdasarkan urutan alami teksnya, yaitu alfabetis dengan huruf besar mendahului huruf kecil pada pembandingan karakter. Pemanggilan pada array kosong atau berisi satu elemen berjalan tanpa melakukan apa pun, sehingga tidak perlu pengkondisian khusus sebelum mengurutkan. Bila hanya sebagian array yang ingin diurutkan, tersedia overload sort(array, dariInklusif, sampaiEksklusif) yang mengurutkan rentang tersebut saja. Urutan kustom untuk tipe objek tertentu dipenuhi dengan menyediakan Comparator, sehingga sort tidak lagi bergantung pada urutan alami elemennya.

Menyalin dengan copyOf dan copyOfRange#

Arrays.copyOf membuat array baru dengan panjang yang ditentukan dan mengisi salinannya dari elemen array asal. Arrays.copyOfRange melakukan hal serupa untuk satu rentang indeks saja. Keduanya penting karena array tidak bisa diubah ukurannya, sehingga perluasan array selalu berarti membuat array baru.

java SalinArray.java
import java.util.Arrays;

public class SalinArray {
    public static void main(String[] args) {
        int[] asal = {10, 20, 30, 40, 50};

        int[] salinanPenuh = Arrays.copyOf(asal, asal.length);
        int[] dipendekkan = Arrays.copyOf(asal, 3);
        int[] diperpanjang = Arrays.copyOf(asal, 7);
        int[] potongan = Arrays.copyOfRange(asal, 1, 4);

        salinanPenuh[0] = 99;

        System.out.println(Arrays.toString(asal));
        System.out.println(Arrays.toString(salinanPenuh));
        System.out.println(Arrays.toString(dipendekkan));
        System.out.println(Arrays.toString(diperpanjang));
        System.out.println(Arrays.toString(potongan));
    }
}
text Keluaran
[10, 20, 30, 40, 50]
[99, 20, 30, 40, 50]
[10, 20, 30]
[10, 20, 30, 40, 50, 0, 0]
[20, 30, 40]

Program di atas memperlihatkan tiga perilaku sekaligus. Pertama, salinan benar-benar berdiri sendiri, karena mengubah salinanPenuh[0] menjadi 99 tidak menyentuh asal. Kedua, panjang yang diminta lebih kecil memotong elemen yang tersisa, sedangkan panjang yang lebih besar menambah slot kosong berisi nilai default, yaitu 0 untuk tipe primitif dan null untuk tipe referensi. Ketiga, copyOfRange(asal, 1, 4) mengambil indeks 1 sampai 3, karena batas akhirnya bersifat eksklusif.

Mengisi dengan fill#

Arrays.fill menimpa elemen array dengan satu nilai yang sama, sekaligus untuk seluruh array atau untuk satu rentang indeks tertentu. Metode ini cocok untuk menyiapkan nilai awal seragam, misalnya papan permainan berisi tanda kosong, label yang belum ditentukan, atau array pencadangan yang harus direset secara berkala. Nilai yang diberikan harus cocok dengan tipe elemennya, sehingga array int diisi angka dan array String diisi teks.

java IsiArray.java
import java.util.Arrays;

public class IsiArray {
    public static void main(String[] args) {
        int[] papan = new int[6];
        Arrays.fill(papan, 7);

        char[] petak = new char[4];
        Arrays.fill(petak, '-');

        String[] label = new String[3];
        Arrays.fill(label, "kosong");

        System.out.println(Arrays.toString(papan));
        System.out.println(Arrays.toString(petak));
        System.out.println(Arrays.toString(label));
    }
}
text Keluaran
[7, 7, 7, 7, 7, 7]
[-, -, -, -]
[kosong, kosong, kosong]

Pemanggilan fill selalu menimpa nilai lama tanpa peringatan, termasuk nilai default hasil new maupun isi yang sudah dihitung sebelumnya. Bila hanya sebagian array yang perlu diisi, gunakan overload fill(array, dariInklusif, sampaiEksklusif, nilai) yang batas rentangnya mengikuti pola eksklusif yang sama dengan copyOfRange.

Mencari dengan binarySearch#

Arrays.binarySearch mencari satu nilai pada array yang sudah terurut dan mengembalikan indeks tempat nilainya ditemukan. Metode ini membelah rentang pencarian menjadi dua pada setiap langkah, sehingga pencarian pada ribuan elemen hanya memerlukan belasan langkah.

java CariNilai.java
import java.util.Arrays;

public class CariNilai {
    public static void main(String[] args) {
        int[] data = {15, 27, 33, 41, 58, 66, 72, 90};

        int posisi33 = Arrays.binarySearch(data, 33);
        int posisi90 = Arrays.binarySearch(data, 90);
        int posisi50 = Arrays.binarySearch(data, 50);

        System.out.println("posisi 33: " + posisi33);
        System.out.println("posisi 90: " + posisi90);
        System.out.println("posisi 50: " + posisi50);
    }
}
text Keluaran
posisi 33: 2
posisi 90: 7
posisi 50: -5

Nilai yang tidak ada dikembalikan dalam bentuk negatif dengan pola -(titik sisip) - 1. Titik sisip adalah indeks tempat nilai itu seharusnya berada agar array tetap terurut. Pencarian 50 menghasilkan -5 karena posisi yang cocok untuknya adalah indeks 4, sehingga hitungannya -(4) - 1. Pola ini memudahkan pemeriksaan keberadaan sekaligus mengetahui posisi penyisipan. Jumlah langkahnya bertambah hanya satu setiap kali ukuran array berlipat ganda, sifat yang dinyatakan sebagai kompleksitas O(log⁡n)O(\log n) untuk kasus terburuknya.

Arrays.binarySearch(data, 66) pada array yang sudah terurut152733415866729001234567tengah langkah 1ditemukanLangkah 1: rentang 0 sampai 7, tengah indeks 3 berisi 41, 66 lebih besarLangkah 2: rentang 4 sampai 7, tengah indeks 5 berisi 66, ditemukanSetiap langkah membuang separuh rentang, sehingga 8 elemen selesai dalam 2 langkah
binarySearch membelah rentang pencarian setiap langkah hingga nilai ditemukan

Kesalahan umum#

  • Lupa import java.util.Arrays. Kelas ini berada di package java.util, bukan java.lang, sehingga tanpa import nama Arrays tidak dikenali kompilator.
  • Memanggil binarySearch pada array yang belum diurutkan. Hasilnya kelihatan wajar pada array pendek, tetapi sebenarnya tidak terjamin. Urutkan dulu dengan Arrays.sort.
  • Mengira copyOf mengubah array asalnya. Metode ini selalu menghasilkan array baru, sedangkan array asal tetap utuh. Yang berbahaya justru penugasan biasa seperti int[] salinan = asal; yang tidak menyalin apa pun.
  • Memakai Arrays.toString untuk array dua dimensi dan mengira isi barisnya tercetak. Gunakan Arrays.deepToString agar baris di dalamnya ikut disusuri.
  • Mengisi array dengan fill lalu lupa bahwa nilai lama sudah hilang. fill menimpa tanpa syarat, jadi pastikan urutan pemanggilannya benar sebelum perhitungan lain membaca array tersebut.

Ringkasan#

  • Arrays.toString menampilkan isi array satu dimensi, sedangkan deepToString menyusuri array bertingkat, karena pencetakan langsung hanya memunculkan alamat objek.
  • sort mengurutkan menaik di tempat, copyOf dan copyOfRange menyalin dengan ukuran atau rentang baru, dan fill menimpa elemen dengan satu nilai.
  • binarySearch mengembalikan indeks bila ditemukan dan -(titik sisip) - 1 bila tidak, dengan syarat mutlak array sudah terurut.
  • Semua metode tersebut berupa metode static di kelas java.util.Arrays sehingga dipanggil lewat nama kelasnya.

Referensi#