Jumat, 05 Maret 2010

Pemrograman Dengan Array

Array merupakan jenis struktur data yang sangat dasar dan sangat penting. Teknik pengolahan array merupakan teknik pemrograman yang paling penting yang kita harus kuasai. Dua jenis teknik pengolahan array -- pencarian dan pengurutan -- akan dibahas kemudian. Bagian ini akan memperkenalkan beberapa ide dasar pengolahan array secara umum.

Dalam banyak hal, pengolahan array berarti menggunakan operasi yang sama kepada setiap elemen di dalam array. Biasanya sering dilakukan dengan perulangan for. Perulangan untuk mengolah semua elemen dalam array A dapat ditulis dalam bentuk :

// lakukan inisialiasi yang diperlukan sebelumnya
for (int i = 0; i < A.length; i++) {
. . . // proses A[i]
}

Misalnya, A adalah array dengan tipe double[]. Misalnya kita ingin menjumlah semua nilai dalam array tersebut. Algoritma umum untuk melakukannya adalah :

Mulai dengan 0;
Tambah A[0]; (proses elemen pertama di dalam A)
Tambah A[1]; (proses elemen kedua di dalam A)
.
.
.
Tambah A[ A.length - 1 ]; (proses elemen terakhir di dalam A)

Dengan menggunakan pengetahuan yang kita telah pelajari tentang perulangan, kita bisa ubah algoritma di atas menjadi bentuk perulangan for seperti berikut:

double jumlah; // Jumlah nilai di dalam A
jumlah = 0; // Mulai dengan 0
for (int i = 0; i < A.length; i++)
jumlah += A[i]; // tambah A[i] ke dalam jumlah untuk i = 0, 1, ..., A.length - 1

Lihat bahwa kondisi kelanjutan "i < A.length" menyatakan bahwa nilai i terakhir yang akan diolah adalah A.length - 1 yaitu elemen terakhir dalam array. Ingat bahwa kita menggunakan "<" bukan "<=" karena dengan "<=" komputer akan memberikan kesalahan indeks di luar batas.

Pada akhirnya, nanti Anda akan bisa membuat perulangan seperti di atas di luar kepala. Kita akan lihat beberapa contohnya. Di sini perulangan akan menghitung banyaknya elemen di dalam array A yang nilainya kurang dari nol :

int hitung; // Untuk menghitung elemen
hitung = 0; // Mulai dengan nol
for (int i = 0; i < A.length; i++) {
if (A[i] < 0.0) // Jika elemen ini kurang dari nol
hitung++; // tambah hitung dengan 1
}
// Di sini nilai "hitung" adalah banyaknya elemen yang kurang dari 0.

Kita bisa mengganti "A[i] < 0.0" jika kita ingin menghitung banyaknya elemen di dalam array yang memiliki sifat tertentu. Variasinya akan memiliki tema yang sama. Misalnya kita ingin menghitung banyaknya elemen di dalam array A yang sama dengan elemen sesudahnya. Elemen setelah A[i] adalah A[i+1], sehingga kita bisa mengganti klausa if dengan "if (A[i] == A[i+1])". Akan tetapi tunggu dulu : Tes ini tidak bisa digunakan apabila A[i] adalah elemen terakhir dalam array, karena tidak ada lagi array sesudahnya. Komputer akan menolak pernyataan ini. Sehingga kita harus berhenti satu elemen sebelum array terakhir, sehingga menjadi

int hitung = 0;
// lihat kondisi for berubah dibandingkan dengan contoh sebelumnya
for (int i = 0; i < A.length - 1; i++) {
if (A[i] == A[i+1])
hitung++;
}

Masalah umum lainnya adalah mencari nilai terbesar di dalam array A. Strateginya adalah lihat semua isi array, catat nilai terbesar saat itu. Kita akan simpan nilai terbesar yang kita temui dalam variabel maks. Pada saat kita melihat elemen array satu per satu, kapanpun kita melihat nilai elemen tersebut lebih besar dari maks kita akan mengganti nilai maks dengan nilai yang lebih besar tersebut. Setelah semua elemen array diproses, maka maks merupakan nilai elemen terbesar di dalam array tersebut. Pertanyaannya adalah, apa nilai awal maks? Salah satu kemungkinannya adalah mulai dengan nilai maks sama dengan A[0], baru kemudian melihat isi elemen array lainnya mulai dengan A[1]. Misalnya,

double maks = A[0]; // nilai maks berisi elemen array pertama
for (int i = 1; i < A.length; i++) { // i mulai dari elemen kedua
if (A[i] > maks)
max = A[i];
}
// Di sini maks berisi nilai elemen array yang paling besar

(Ada masalah yang lebih penting di sini. Java membolehkan array memiliki panjang nol. Artinya bahkan A[0] pun tidak ada di dalam array, sehingga memanggil A[0] akan menghasilkan kesalahan indeks keluar batas. Akan tetapi array biasanya array dengan panjang nol biasanya sesuatu yang kita ingin hindarkan dalam kehidupan sehari-hari. Lagian apa artinya mencari nilai terbesar di dalam suatu array yang panjangnya nol?)

Contoh terakhir dari operasi array, misalnya kita ingin mengkopi suatu array. Untuk mengkopi array A, tidak cukup untuk menggunakan perintah

double[] B = A;

karena perintah ini tidak membuat objek array baru. Yang dibuat di sini adalah variabel baru yang merujuk pada objek yang sama dengan A. (Sehingga perubahan yang terjadi pada A[i] akan juga menyebabkan B[i] berubah). Untuk membuat array baru yang merupakan kopi dari array A, kita harus membuat objek array baru, dan mengkopi isinya satu per satu dari array A ke array baru, sehingga

// Buat objek array baru, yang panjangnya sama dengan panjang A
double[] B = new double[A.length];

for (int i = 0; i < A.length; i++)
B[i] = A[i]; // Kopi setiap elemen dari A ke B

Mengkopi nilai dari satu array ke array yang lain adalah operasi umum sehingga Java memiliki subrutin untuk melakukannya, yaitu System.arraycopy(), yang merupakan subrutin anggota statik dari kelas standar System. Deklarasinya memiliki bentuk seperti :

public static void arraycopy(Object arraySumber, int indeksAwalSumber,
Object arrayTujuan, int indeksAwalTujuan, int jumlah)

di mana arraySumber dan arrayTujuan bisa berbentuk array dengan tipe apapun. Nilai akan dikopi dari arraySumber ke arrayTujuan. jumlah adalah berapa banyak elemen yang akan dikopi. Nilai akan dikopi dari arraySumber mulai dari posisi indeksAwalSumber dan akan disimpan pada arrayTujuan mulai dari posisi indeksAwalTujuan. Misalnya kita akan mengkopi array A, maka kita bisa menggunakan perintah

double B = new double[A.length];
System.arraycopy( A, 0, B, 0, A.length );

Suatu tipe array, misalnya double[] adalah tipe Java biasa, sehingga kita bisa menggunakannya seperti tipe-tipe Java lainnya. Termasuk juga digunakan sebagai parameter formal di dalam suatu subrutin. Juga bisa digunakan sebagai tipe keluaran suatu fungsi. Misalnya, kita bisa menulis fungsi yang membuat kopi array dengan tipe double sebagai berikut :

double[] kopi( double[] sumber ) {
// Membuat dan mengembalikan kopi array sumber
// Jika sumber null, maka kembalikan null
if ( sumber == null )
return null;
double[] kpi; // Kopi array sumber
kpi = new double[sumber.length];
System.arraycopy( sumber, 0, kpi, 0, sumber.length );
return kpi;
}

Rutin main() memiliki parameter dengan tipe String[] yang merupakan array String. Ketika sistem memanggil rutin main(), string di dalam array ini adalah parameter dari baris perintah. Jika kita menggunakan konsol, user harus mengetikkan perintah untuk menjalankan program. User bisa menambahkan input tambahan dalam perintah ini setelah nama program yang akan dijalankan.

Misalnya, jika kelas yang memiliki rutin main() bernama programKu, maka user bisa menjalankan kelas tersebut dengan perintah "java programKu" di konsol. Jika kita tulis dengan "java programKu satu dua tiga", maka parameter dari baris perintahnya adalah "satu", "dua", dan "tiga". Sistem akan memasukkan parameter-parameter ini ke dalam array String[] dan memberikan array ini pada rutin main().

Berikut ini adalah contoh program sederhana yang hanya mencetak parameter dari baris perintah yang dimasukkan oleh user.

public class CLDemo {
public static void main(String[] args) {
System.out.println("Anda memasukkan " + args.length
+ " parameter dari baris perintah");
if (args.length > 0) {
System.out.println("Parameter tersebut adaah :");
for (int i = 0; i < args.length; i++)
System.out.println(" " + args[i]);
}
} // akhir main()
} // akhir kelas CLDemo

Perhatikan bahwa parameter args tidak mungkin null meskipun tidak ada parameter yang dimasukkan. Jika tidak ada parameter dari baris perintah yang dimasukkan, maka panjang array ini adalah nol.

Hingga sekarang, contoh yang telah diberikan adalah bagaimana mengolah array dengan mengakses elemennya secara berurutan (sequential access). Artinya elemen-elemen array diproses satu per satu dalam urutan dari awal hingga akhir. Akan tetapi salah satu keuntungan array adalah bahwa array bisa digunakan untuk mengakses elemennya secara acak, yaitu setiap elemen bisa diakses kapan saja secara langsung.

Misalnya, kita ambil contoh suatu masalah yang disebut dengan masalah ulang tahun: Misalnya ada N orang di dalam suatu ruangan. Berapa kemungkinan dua orang di dalam ruangan tersebut memiliki ulang tahun yang sama (yang dilahirkan pada tanggal dan bulan yang sama, meskipun tahunnya berbeda)? Kebanyakan orang salah menerka jawabannya. Sekarang kita lihat dengan versi masalah yang berbeda: Misalnya kita memilih orang secara acak dan menanyakan ulang tahunnya. Berapa orang yang Anda harus tanya untuk mendapatkan hari ulang tahun yang sama dengan orang sebelumnya?

Tentunya jawabannya akan tergantung pada faktor yang bersifat acak, akan tetapi kita bisa simulasikan dengan program komputer dan menjalankan beberapa kali hingga kita tahu berapa kira-kira orang harus dicek.

Untuk mensimulasikan percobaan ini, kita harus mencatat semua ulang tahun yang kita sudah tanyakan. Ada 365 kemungkinan hari ulang tahun (Kita abaikan sementara tahun kabisat). Untuk setiap kemungkinan hari ulang tahun, kita perlu tahu, apakah hari ulang tahun tersebut telah digunakan? Jawabannya adalah nilai boolean true atau false. Untuk menyimpan data ini, kita bisa gunakan array dari 365 nilai boolean:

boolean[] sudahDitanya;
sudahDitanya = new boolean[365];

Tanggal-tanggal pada satu tahun dinomori dari 0 hingga 364. Nilai sudahDitanya[i] akan bernilai true jika orang yang kita tanya berulang tahun pada hari tersebut. Pada awalnya semua nilai pada array sudahDitanya[i] bernilai false. Ketika kita memilih satu orang dan menanyakan hari ulang tahunnya, misalnya i, kita akan mengecek terlebih dahulu apakah sudahDitanya[i] bernilai true. Jika tidak maka orang ini adalah orang kedua dengan ulang tahun yang sama. Artinya kita sudah selesai.

Jika sudahDitanya[i] bernilai false, maka belum ada orang sebelum ini yang memiliki hari ulang tahun tersebut. Kita akan ganti sudahDitanya[i] dengan true, kemudian kita akan tanyakan lagi kepada orang lain, dan begitu seterusnya hingga semua orang di dalam ruangan ditanyakan.

static void masalahUlangTahun() {
// Melakukan simulasi dengan memilih seseorang secara acak
// dan mengecek hari ulang tahunnya. Jika hari ulang tahunnya
// sama dengan orang yang pernah kita tanya sebelumnya,
// hentikan program dan laporkan berapa orang yang sudah dicek

boolean[] sudahDitanya;
// Untuk mencatat ulang tahun yang sudah ditanyakan
// Nilai true pada sudahDitanya[i] berarti orang lain
// sudah ada yang berulang tahun pada hari i

int hitung;
// Jumlah orang yang sudah pernah ditanya

sudahDitanya = new boolean[365];
// Awalnya, semua nilai adalah false

hitung = 0;

while (true) {
// Ambil ulang tahun secara acak dari 0 hingga 364
// Jika ulang tahun telah ditanya sebelumnya, keluar
// Jika tidak catat dalam array

int ultah; // Ulang tahun seseorang
ultah = (int)(Math.random()*365);
hitung++;
if ( sudahDitanya[ultah] )
break;
sudahDitanya[ultah] = true;
}

System.out.println("Ulang tahun yang sama ditemukan setelah menanyakan "
+ hitung + " orang.");

} // akhir masalahUlangTahun()

Subrutin ini menggunakan fakta bahwa array boolean yang baru dibuat memiliki seluruh elemen yang bernilai false. Jika kita ingin menggunakan array yang sama untuk simulasi kedua, kita harus mereset ulang semua elemen di dalamnya menjadi false kembali dengan perulangan for

for (int i = 0; i < 365; i++)
sudahDitanya[i] = false;

Array paralel adalah menggunakan beberapa array dengan indeks yang sama. Misalnya kita ingin membuat beberapa kolom secara paralel -- array x di kolom pertama, array y di kolom kedua, array warna di kolom ketiga, dan seterusnya. Data untuk baris ke-i bisa didapatkan dari masing-masing array ini. Tidak ada yang salah dengan cara ini, akan tetapi cara ini berlawanan dengan filosofi berorientasi objek yang mengumpulkan data yang berhubungan di dalam satu objek. Jika kita mengikuti aturan seperti ini, amaka kita tidak harus membayangkan hubungan data yang satu dan yang lainnya karena semua data akan dikelompokkan di dalam satu tempat.

Misalnya saya menulis kelas seperti

class DataString {
// Data dari salah satu pesan
int x,y; // Posisi pesan
Color warna; // Warna pesan
}

Untuk menyimpan data dalam beberapa pesan, kita bisa menggunakan array bertipe DataString[], yang kemudian dideklarasikan sebagai variabel instansi dengan nama data sehingga

DataString[] data;

Isi dari data bernilai null hingga kita membuat array baru, misalnya dengan

data = new DataString[JUMLAH_PESAN];

Setelah array ini dibuat, nilai setiap elemen array adalah null. Kita ingin menyimpan data di dalam objek yang bertipe DataString, akan tetapi tidak ada objek yang dibuat. Yang kita sudah buat hanyalah kontainernya saja. Elemen di dalamnya berupa objek yang belum pernah kita buat. Untuk itu elemen di dalamnya bisa kita buat dengan perulangan for seperti :

for (int i = 0; i < JUMLAH_PESAN; i++)
data[i] = new DataString();

Sekarang kita bisa mengambil data setiap pesan dengan data[i].x, data[i].y, dan data[i].warna.

Terakhir berkaitan dengan pernyataan switch. Misalnya kita memiliki nilai bulan dari 0 hingga 11, yang melambangkan bulan dalam satu tahun dari Januari hingga Desember. Kita ingin mencetaknya di layar, dengan perintah

switch (bulan) {
case 0:
bulanString = "Januari";
break;
case 1:
bulanString = "Februari";
break;
case 2:
bulanString = "Maret";
break;
case 3:
bulanString = "April";
break;
.
.
.
case 11:
bulanString = "Desember";
break;
default:
bulanString = "Salah bulan";
}

Kita bisa mengganti keseluruhan perintah switch tersebut dengan menggunakan array, misalnya dengan array namaBulan yang dideklarasikan sebagai berikut :

static String[] namaBulan = { "Januari", "Februari", "Maret",
"April", "Mei", "Juni", "Juli", "Agustus", "September",
"Oktober", "November", "Desember" };

Kemudian kita bisa ganti keseluruhan switch di atas dengan

bulanString = namaBulan[bulan];

Array Dinamis

Panjang suatu array tidak bisa diubah setelah dibuat. Akan tetapi, sering kali jumlah data yang disimpan dalam array bisa berubah setiap saat. Misalnya dalam contoh berikut : Suatu array menyimpan baris teks dalam program pengolah kata. Atau suatu array yang menyimpan daftar komputer yang sedang mengakses halaman suatu website. Atau array yang berisi gambar yang ditambahkan user oleh program gambar. Di sini jelas, bahwa kita butuh sesuatu yang bisa menyimpan data di mana jumlahnya tidak tetap.

Array Setengah Penuh

Bayangkan suatu aplikasi di mana sejumlah item yang ingin kita simpan di dalam array akan berubah-ubah sepanjang program tersebut berjalan. Karena ukuran array tidak bisa diubah, maka variabel terpisah digunakan untuk menyimpan berapa banyak sisa tempat kosong yang masih bisa diisi di dalam array.

Bayangkan misalnya, suatu program yang membaca bilangan bulat positif dari user, kemudian menyimpannya untuk diproses kemudian. Program akan berhenti membaca input apabila input yang diterima bernilai 0 atau kurang dari nol. Bilangan input n tersebut kita simpa di dalam array bilangan dengan tipe int[]. Katakan banyaknya bilangan yang bisa disimpan tidak lebih dari 100 buah. Maka ukuran array bisa dibuat 100.

Akan tetapi program tersebut harus melacak berapa banyak bilangan yang sudah diambil dari user. Kita gunakan variabel terpisah bernama jmlBilangan. Setiap kali suatu bilangan disimpan di dalam array, nilai jmlBilangan akan bertambah satu.

Sebagai contoh sederhana, masi kita buat program yang mengambil bilangan yang diinput dari user, kemudian mencetak bilangan-bilangan tersebut dalam urutan terbalik. (Ini adalah contoh pengolahan yang membutuhkan array, karena semua bilangan harus disimpan pada suatu tempat. Banyak lagi contoh program misalnya, mencari jumlah atau rata-rata atau nilai maksimum beberapa bilangan, bisa dilakukan tanpa menyimpan bilangan tersebut satu per satu)

public class BalikBilanganInput {

public static void main(String[] args) {

int[] bilangan; // Array untuk menyimpan nilai input dari user
int jmlBilangan; // Banyaknya bilangan yang sudah disimpan dalam array
int bil; // Bilangan yang diambil dari user

bilangan = new int[100]; // Buat array dengan 100 bilangan int
jmlBilangan = 0; // Belum ada bilangan yang disimpan

System.out.println("Masukkan bilangan bulat positif (paling banyak 100 bilangan)" +
", masukkan nol untuk mengakhiri.");

while (true) {
System.out.print("? ");
bil = KonsolIO.ambilInt();
if (bil <= 0)
break;
bilangan[jmlBilangan] = bil;
jmlBilangan++;
}

System.out.println("\nBilangan yang Anda masukkan dalam urutan terbalik adalah :\n");

for (int i = jmlBilangan - 1; i >= 0; i--) {
System.out.println( bilangan[i] );
}

} // akhir main();

} // akhir kelas BalikBilanganInput

Penting untuk diingat bahwa jmlBilangan memiliki dua peran. Yang pertama, adalah melacak banyaknya bilangan yang sudah dimasukkan di dalam array. Yang kedua adalah menentukan di mana indeks kosong berikutnya di dalam array. Misalnya, jika 4 bilangan sudah dimasukkan ke dalam array, maka bilangan-bilangan tersebut diisi pada array di posisi 0, 1, 2, dan 3. Maka posisi kosong berikutnya adalah posisi 4.

Ketika kita akan mencetak angka di dalam array, maka poisisi penuh berikutnya adalah di lokasi jmlBilangan - 1, sehingga perulangan for mencetak bilangan dari jmlBilangan - 1 hingga 0.

Mari kita lihat contoh lain yang lebih realistis. Misalkan kita ingin menulis program game, di mana pemain bisa masuk ke dalam game dan keluar dari game setiap saat. Sebagai programmer berorientasi objek yang baik, mungkin kita memiliki kelas bernama Pemain sebagai lambang pemain di dalam game. Daftar pemain yang sedang ada di dalam game, bisa disimpan di dalam array ArrayPemain dengan tipe Pemain[].

Karena jumlah pemain bisa berubah-ubah maka kita bisa menggunakan variabel bantu, misalnya jumlahPemainAktif untuk mencatat banyaknya pemain yang sedang aktif berada di dalam game. Misalnya jumlah maksimum pemain di dalam game adalah 10 orang, maka kita bisa mendeklarasikan variabelnya sebagai :

Pemain[] ArrayPemain = new Pemain[10]; // Hingga 10 pemain.
int jumlahPemainAktif = 0; // Di awal game, tidak ada pemain yang aktif

Setelah beberapa pemain masuk ke dalam game, variabel jumlahPemainAktif akan lebih dari 0, dan objek pemailn akan disimpan dalam array, misalnya ArrayPemain[0], ArrayPemain[1], ArrayPemain[2], dan seterusnya. Ingat bahwa pemain ArrayPemain[jumlahPemainAktif] tidak ada. Prosedur untuk menambah pemain baru, secara sederhana :

// Tambah pemain di tempat kosong
ArrayPemain[jumlahPemainAktif] = pemainBaru;
// And increment playerCt to count the new player.
jumlahPemainAktif++;

Untuk menghapus seorang pemain mungkin sedikit lebih sulit karena kita tidak ingin meninggalkan lubang di tengah-tengah array. Misalnya kita ingin menghapus pemain pada indeks k pada ArrayPemain. Jika kita tidak peduli urutan pemainnya, maka salah satu caranya adalah memindahkan posisi pemain terakhir ke posisi pemain yang meninggalkan game, misalnya :

ArrayPemain[k] = ArrayPemain[jumlahPemainAktif - 1];
jumlahPemainAktif--;

Pemain yang sebelumnya ada di posisi k, tidak lagi ada di dalam array. Pemain yang sebelumnya ada di posisi jumlahPemainAktif -1 sekarang ada di array sebanyak 2 kali. Akan tetapi sekarang ia berada di bagian yang valid, karena nilai jumlahPemainAktif kita kurangi dengan satu. Ingat bahwa setiap elemen di dalam array harus menyimpan satu nilai, akan tetapi satu-satunya nilai dari posisi 0 hingga jumlahPemainAktif - 1 akan tetap diproses seperti biasa.

Misalnya kita ingin menghapus pemain di posisi k, akan tetapi kita ingin agar urutan pemain tetap sama. Untuk melakukannya, semua pemain di posisi k+1 ke atas harus dipindahkan satu posisi ke bawah. Pemain k+ mengganti pemain k yang keluar dari game. Pemain k+2 mengganti pemain yang pindah sebelumnya, dan berikutnya. Kodenya bisa dibuat seperti

for (int i = k+1; i < jumlahPemainAktif; i++) {
ArrayPemain[i-1] = ArrayPemain[i];
}
jumlahPemainAktif--;

Perlu ditekankan bahwa contoh Pemain di atas memiliki tipe dasar suatu kelas. Elemennya bisa bernilai null atau referensi ke suatu objek yang bertipe Pemain, Objek Pemain sendiri tidak disimpan di dalam array, hanya referensinya saja yang disimpan di sana. Karena aturan pemberian nilai pada Java, objek tersebut bisa saja berupa kelas turunan dari Pemain, sehingga mungkin juga array tersebut menyimpan beberapa jenis Pemain misalnya pemain komputer, pemain manusia, atau pemain lainnya, yang semuanya adalah kelas turunan dari Pemain.

Contoh lainnya, misalnya kelas BentukGeometri menggambarkan suatu bentuk geometri yang bisa digambar pada layar, dan ia memiliki kelas-kelas turunan yang merupakan bentuk-bentuk khusus, seperti garis, kotak, kotak bertepi bulat, oval, atau oval berisi warna, dan sebagainya. (BentukGeometri sendiri bisa berbentuk kelas abstrak, seperti didiskusikan sebelumnya). Kemudian array bertipe BentukGeometri[] bisa menyimpan referensi objek yang bertipe kelas turunan dari BentukGeometri. Misalnya, perhatikan contoh pernyataan berikut

BentukGeometri[] gambar = new BentukGeometri[100]; // Array untuk menyimpan 100 gambar.
gambar[0] = new Kotak(); // Letakkan beberapa objek di dalam array.
gambar[1] = new Garis(); // (Program betulan akan menggunakan beberapa
gambar[2] = new OvalBerwarna(); // parameter di sini
int jmlGambar = 3; // Lacak jumlah objek di dalam array

bisa diilustrasikan sebagai berikut.

Array tersebut bisa digunakan dalam program gambar. Array bisa digunakan untuk menampung gambar-gambar yang akan ditampilkan. Jika BentukGeometri memiliki metode "void gambarUlang(Graphics g)" untuk menggambar pada grafik g, maka semua grafik dalam array bisa digambar dengan perulangan sederhana

for (int i = 0; i < jmlGambar; i++)
gambar[i].gambarUlang(g);

Pernyataan "gambar[i].gambarUlang(g);" memanggil metode gambarUlang() yang dimiliki oleh masing-masing gambar pada indeks i di array tersebut. Setiap objek tahu bagaimana menggambar dirinya sendiri, sehingga perintah dalam perulangan tersebut sebetulnya melakukan tugas yang berbeda-beda tergantung pada objeknya. Ini adalah contoh dari polimorfisme dan pengolahan array.

Array Dinamis

Dalam contoh-contoh di atas, ada batas tententu dalam jumlah elemennya, yaitu 100 int, 100 Pemain, dan 100 BentukGeometris. Karena ukuran array tidak bisa berubah, array tersebut hanya bisa menampung maksimum sebanyak elemen yang didefinisikan pada pembuatan array. Dalam banyak kasus, adanya batas maksimum tersebut tidak diinginkan. Kenapa harus bekerja dengan hanya 100 bilangan bulat saja, bukan 101?

Alternatif yang umum adalah membuat array yang sangat besar sehingga bisa digunakan untuk dalam kehidupan sehari-hari. Akan tetapi cara ini tidak baik, karena akan sangat banyak memori komputer yang terbuang karena tidak digunakan. Memori itu mungkin lebih baik digunakan untuk yang lain. Apalagi jika komputer yang akan digunakan tidak memiliki memori yang cukup untuk menjalankan program tersebut.

Tentu saja, cara yang lebih baik adalah apabila kita bisa mengubah ukuran array sesuka kita kapan saja. Ingat bahwa sebenarnya variabel array tidak menyimpan array yang sesungguhnya. Variabel ini hanya menyimpan referensi ke objek tersebut. Kita tidak bisa membuat array tersebut lebih besar, akan tetapi kita bisa membuat array baru yang lebih besar, kemudian mengubah isi variabel array tersebut ke array baru itu.

Tentunya kita harus mengkopi semua isi di array yang lama ke array baru. Array lama akan diambil oleh pemulung memori, karena ia tidak lagi digunakan.

Mari kita lihat kembali contoh game di atas, di mana ArrayPemain adalah array dengan tipe Pemain[] dan jumlahPemainAktif[/code] adalah jumlah pemain yang sudah digunakan array tersebut. Misalnya kita tidak ingin membuat limit banyaknya pemainnya yang bisa ikut main. Jika pemain baru masuk dan array tersebut sudah penuh, kita akan membuat array baru yang lebih besar.

Variabel ArrayPemain akan merujuk pada array baru. Ingat bahwa setelah ini dilakukan, ArrayPemain[0] akan menunjuk pada lokasi memori yang berbeda, akan tetapi nilai ArrayPemain[0] sama dengan sebelumnya. Berikut ini adalah kode untuk melakukan hal di atas:

// Tambah pemain baru, meskipun array sudah penuh

if (jumlahPemainAktif == ArrayPemain.length) {
// Array sudah penuh. Buat array baru yang lebih besar,
// kemudian kopi isi array lama ke array baru lalu ubah
// ArrayPemain ke array baru.
int ukuranBaru = 2 * ArrayPemain.length; // Ukuran array baru
Pemain[] temp = new Pemain[ukuranBaru]; // Array baru
System.arraycopy(ArrayPemain, 0, temp, 0, ArrayPemain.length);
ArrayPemain = temp; // Ubah referensi ArrayPemain ke array baru.
}

// Di sini kita sudah tahu bahwa pasti ada tempat di array baru.

ArrayPemain[jumlahPemainAktif] = pemainBaru; // Tambah pemain baru...
jumlahPemainAktif++; // ... dan tambah satu jumlahPemainAktif nya

Jika kita akan melakukan hal ini terus menerus, akan lebih indah jika kita membuat kelas untuk menangani hal ini. Objek mirip array yang bisa berubah ukuran untuk mengakomodasi jumlah data yang bisa ia tampung disebut array dinamis. Array dinamis memiliki jenis operasi yang sama dengan array : mengisi nilai pada posisi tertentu dan mengambil nilai di posisi tertentu. Akan tetapi tidak ada batas maksimum dari jumlah array (hanya tergantung pada jumlah memori komputer yang tersedia). Dalam kelas array dinamis, metode put dan get akan diimplementasikan sebagai metode instansi.

Di sini misalnya, adalah kelas yang mengimplementasikan array dinamis int :

public class ArrayDinamisInt {
private int[] data; // Array untuk menyimpan data
public DynamicArrayOfInt() {
// Konstruktor.
data = new int[1]; // Array akan bertambah besar jika diperlukan
}

public int get(int posisi) {
// Ambil nilai dari posisi tertentu di dalam array.
// Karena semua posisi di dalam array adalah nol, maka
// jika posisi tertentu di luar data array, nilai 0 akan dikembalikan
if (posisi >= data.length)
return 0;
else
return data[posisi];
}

public void put(int posisi, int nilai) {
// Simpan nilai ke posisi yang ditentukan di dalam array
// Data array tersebut akan bertambah besar jika diperlukan

if (posisi >= data.length) {
// Posisi yang ditentukan berada di luar array data
// Besarkan ukuran array 2x lipat. Atau jika ukurannya masih
// terlalu kecil, buat ukurannya sebesar 2*posisi

int ukuranBaru = 2 * data.length;
if (posisi >= ukuranBaru)
ukuranBaru = 2 * posisi;
int[] dataBaru = new int[ukuranBaru];
System.arraycopy(data, 0, dataBaru, 0, data.length);
data = dataBaru;

// Perintah berikut hanya untuk demonstrasi
System.out.println("Ukuran array dinamis diperbesar menjadi "
+ ukuranBaru);
}
data[posisi] = nilai;
}

} // akhir kelas ArrayDinamisInt

Data pada objek ArrayDinamisInt disimpan dalam array biasa, akan tetapi arraynya akan dibuang dan diganti dengan array baru yang lebih besar apabila diperlukan. Jika bilangan adalah variable bertipe ArrayDinamisInt, maka perintah bilangan.put(pos,nilai) akan menyimpan bilangan pada posisi pos di array dinamis tersebut. Fungsi bilangan.get(pos) mengambil nilai yang disimpan pada posisi pos.

Pada contoh pertama, kita menggunakan array untuk menyimpan bilangan bulat positif yang dimasukkan oleh user. Kita bisa menulis ulang program tersebut dengan menggunakan ArrayDinamisInt. Referensi ke bilangan[i] diganti dengan bilangan.get[i]. Perintah "bilangan[jmlBilangan] = bil;" kita ganti dengan "bilangan.put(jmlBilangan,bil);". Berikut ini adalah programnya:

public class BalikBilanganInput {

public static void main(String[] args) {

ArrayDinamisInt bilangan; // Array untuk menyimpan nilai input dari user
int jmlBilangan; // Banyaknya bilangan yang sudah disimpan dalam array
int bil; // Bilangan yang diambil dari user

bilangan = new ArrayDinamisInt();
jmlBilangan = 0; // Belum ada bilangan yang disimpan

System.out.println("Masukkan bilangan bulat positif, masukkan nol untuk mengakhiri.");

while (true) {
System.out.print("? ");
bil = KonsolIO.ambilInt();
if (bil <= 0)
break;
bilangan.put(jmlBilangan,bil);
jmlBilangan++;
}

System.out.println("\nBilangan yang Anda masukkan dalam urutan terbalik adalah :\n");

for (int i = jmlBilangan - 1; i >= 0; i--) {
System.out.println( bilangan.get(i) );
}

} // akhir main();

} // akhir kelas BalikBilanganInput

Membuat Dan Menggunakan Array

Jika sekumpulan data digabungkan dalam satu unit, hasilnya adalah suatu struktur data. Data struktur dapat berupa struktur yang sangat kompleks, akan tetapi dalam banyak aplikasi, data struktur yang cocok hanya terdiri dari kumpulan data berurutan. Struktur data sederhana seperti ini bisa berupa array atau record.

Istilah "record" sebetulnya tidak digunakan pada Java. Suatu record pada intinya mirip dengan objek pada Java yang hanya memiliki variabel instansi tanpa metode instansi. Beberapa bahasa pemrograman lain yang tidak mendukung objek biasanya mendukung record. Dalam bahasa C yang bukan bahasa berorientasi objek, misalnya, memiliki tipe data record, dimana pada C disebut "struct". Data pada record -- dalam Java, adalah variabel instansi suatu objek -- disebut field suatu record. Masing-masing item disebut nama field. Dalam Java, nama field adalah nama variabel instansi. Perbedaan sifat dari suatu record adalah bahwa item pada record dipanggil berdasarkan namanya, dan field yang berbeda dapat berupa tipe yang berbeda. Misalnya, kelas Orang didefisikan sebagai :

class Orang {
String nama;
int nomorID;
Date tanggalLahir;
int umur;
}

maka objek dari kelas Orang bisa disebut juga sebagai record dengan 4 field. Nama fieldnya adalah nama, nomorID, tanggalLahir dan umur. Lihat bahwa tipe datanya berbeda-beda yaitu String, int, dan Date.

Karena record hanya merupakan bagian lebih kecil dari objek, kita tidak akan bahas lebih lanjut di sini.

Seperti record, suatu array adalah kumpulan item. Akan tetapi, item pada record dipanggil dengan nama, sedangkan item pada array dinomori, dan masing-masing item dipanggil besarkan nomor posisi pada array tersebut. Semua item pada array harus bertipe sama. Definisi suatu array adalah : kumpulan item bernomor yang semuanya bertipe sama. Jumlah item dalam suatu array disebut panjang array. Nomor posisi dari array disebut indeks item tersebut dalam array. Tipe dari item tersebut disebut tipe dasar dari array.

Tipe dasar suatu array bisa berupa tipe Java apa saja, baik berupa tipe primitif, nama kelas, atau nama interface. Jika tipe dasar suatu array adalah int, maka array tersebut disebut "array int". Suatu array bertipe String disebut "array String". Akan tetapi array bukan urutan int atau urutan String atau urutan nilai bertipe apapun. Lebih baik jika array adalah urutan variabel bertipe int atau String atau tipe lainnya.

Seperti biasa, ada dua kemungkinan kegunaan variabel : sebagai nama suatu lokasi di memori, dan nama suatu nilai yang disimpan pada lokasi memori. Setiap posisi pada array bersifat seperti variabel. Setiap posisi dapat menyimpan nilai dengan tipe tertentu (yaitu tipe dasar array). Isinya bisa diganti kapanpun. Nilai tersebut disimpan di dalam array. Array merupakan kontainer bukan kumpulan nilai.

Item pada array (maksudnya setiap anggota variabel dalam array tersebut) sering juga disebut elemen array. Dalam Java, elemen array selalu dinomori mulai dari nol. Yaitu, indeks dari elemen pertama suatu array adalah nol. Jika panjang array adalah N, maka indeks elemen terakhir adalah N-1. Sekali array dibuat, maka panjangnya tidak bisa diubah lagi.

Dalam Java, array adalah objek. Ada beberapa konsekuensi yang lahir dari fakta ini. Array harus dibuat dengan operator new. Variabel tidak bisa menyimpan array; variabel hanya bisa merujuk pada array. Variabel lain yang bisa merujuk array juga bisa bernilai null yang berarti ia tidak merujuk pada lokasi memori apapun. Seperti objek lain, array juga bagian dari suatu kelas, di mana seperti kelas lain adalah kelas turunan dari kelas Object. Elemen array pada dasarnya adalah variabel instansi dalam objek array, kecuali mereka dipanggil dalam indeksnya bukan namanya.

Meskipun array berupa objek, ada beberapa perbedaan antara array dan objek lainnya, dan ada beberapa fitur khusus Java untuk membuat dan menggunakan array.

Misalnya A adalah variabel yang merujuk pada suatu array. Maka indeks k di dalam A bisa dipanggil dengan A[k]. Item pertama adalah A[0], yang kedua adalah A[i], dan seterusnya. A[k] adalah suatu variabel dan bisa digunakan seperti variabel lainnya. Kita bisa memberinya nilai, bisa menggunakannya dalam ekspresi, dan bisa diberikan sebagai parameter pada subrutin. Semuanya akan didiskusikan di bawah nanti. Untuk sekarang ingat sintaks berikut

variabel_array [ekspresi_integer]

untuk merujuk pada suatu array.

Meskipun setiap array merupakan suatu objek, kelas array tidak harus didefinisikan sebelumnya. Jika suatu tipe telah ada, maka kelas array dari tipe tersebut otomatis ada. Jika nama suatu tipe adalah TipeDasar, maka nama kelas arraynya adalah TipeDasar[]. Artinya, suatu objek yang diciptakan dari kelas TipeDasar[] adalah array dari item yang tiap itemnya bertipe TipeDasar. Tanda kurung "[]" dimaksudkan untuk mengingat sintaks untuk mengambil item di dalam suatu array. "TipeDasar[]" dibaca seperti "array TipeDasar". Mungkin perlu juga dijelaskan bahwa jika KelasA adalah kelas turunan dari KelasB maka KelasA[] otomatis menjadi kelas turunan KelasB[].

Tipe dasar suatu array dapat berupa tipe apapun yang ada atau sudah didefinisikan pada Java. Misalnya tipe primitif int akan diturunkan kelas array int[]. Setiap elemen di dalam array int[] adalah variabel yang memiliki tipe int dan bisa diisi dengan nilai dengan tipe int. Dari kelas yang bernama String diturunkan tipe array String[]. Setiap elemen di dalam array String[] adalah variabel dengan tipe String, yang bisa diisi dengan nilai bertipe String. Nilai ini bisa null atau referensi ke objek yang bertipe String (dan juga kelas turunan dari String)

Mari kita lihat contoh lebih konkrotnya menggunakan array bilangan bulat sebagai contoh pertama kita. Karena int[] adalah sebuah kelas, maka kita bisa menggunakannya untuk mendeklarasikan variabel. Misalnya,

int[] daftar;

yang membuat variabel bernama daftar dengan tipe int[]. Variabel ini bisa menunjuk pada array int, akan tetapi nilai awalnya adalah null (jika merupakan variabel anggota suatu kelas) atau tak tentu (jika merupakan variabel lokal di dalam suatu metode). Operator new digunakan untuk membuat objek array baru, ayng kemudian bisa diberikan kepada daftar. Sintaksnya sama seperti sintaks sebelumnya, yaitu :

daftar = new int[5];

membuat array 5 buah integer. Lebih umum lagi, konstruktor "new TipeDasar[N]" digunakan untuk membuat array bertipe TipeDasar[]. Nilai N di dalam kurung menyatakan panjang array, atau jumlah elemen yang bisa ditampung. Panjang array adalah variabel instansi di dalam objek array, sehingga array tahu berapa panjangnya. Kita bisa mendapatkan panjang suatu array, misalnya daftar menggunakan daftar.length (akan tetapi kita tidak bisa mengubahnya)

Hasil dari pernyataan "daftar = new int[5];" dapat diilustrasikan sebagai berikut

Ilustrasi array int

Perlu dicatat bahwa array integer secara otomatis diisi dengan nol. Dalam Java, array yang baru dibuat akan selalu diisi dengan nilai tertentu: nol untuk angka, false untuk boolean, karakter dengan nilai Unicode 0 untuk char dan null untuk objek.

Elemen di dalam array daftar dapat dirujuk dengan daftar[0], daftar[1], daftar[2], daftar[3], dan daftar[4] (ingat juga bahwa nilai indeks terbesar adalah panjangnya array dikurang satu). Akan tetapi, referensi array sebetulnya lebih umum lagi. Tanda kurung di dalam referensi array bisa berisi ekspresi apapun yang nilainya suatu integer. Misalnya jika idks adalah variabel bertipe int, maka daftar[idks] dan daftar[2*idks+3] secara sintaks benar.

Contoh berikut akan mencetak semua isi integer di dalam array daftar ke layar :

for (int i = 0; i < daftar.length; i++) {
System.out.println( daftar[i] );
}

Perulangan pertama adalah ketika i = 0, dan daftar[i] merujuk pada daftar[0]. Jadi nilai yang disimpan pada variabel daftar[0] akan dicetak ke layar. Perulangan kedua adalah i = 1, sehingga nilai daftar[i] dicetak. Perulangan berhenti setelah mencetak daftar[4] dan i menjadi sama dengan 5, sehingga kondisi lanjutan "i < daftar.length" tidak lagi benar. Ini adalah contoh umum dari menggunakan perulangan untuk mengolah suatu array.

Penggunaan suatu variabel dalam suatu program menyatakan lokasi di memori. Pikirkan sesaat tentang apa yang akan komputer lakukan ketika ia menemukan referensi ke elemen suatu array daftar[k] ketika program berjalan. Komputer harus menentukan lokasi memori di mana ia dijadikan referensi. Untuk komputer, daftar[k] berarti : "Ambil pointer yang disimpan di dalam variabel daftar. Ikuti pointer ini untuk mencari objek array. Ambil nilai k. Pergi ke posisi ke-k dari array tersebut, dan di sanalah alamat memori yang Anda ingin."

Ada dua hal yang bisa salah di sini. Misalnya nilai daftar adalah null. Dalam kasus ini, maka daftar tidak memiliki referensi sama sekali. Percobaan merujuk suatu elemen pada suatu array kosong adalah suatu kesalahan. Kasus ini akan menampilkan pesan kesalahan "pointer kosong". Kemungkinan kesalahan kedua adalah jika daftar merujuk pada suatu array, akan tetapi k berada di luar rentang indeks yang legal. Ini akan terjadi jika k < 0 atau jika k >= daftar.length. Kasus ini disebut kesalahan "indeks array keluar batas". Ketika kita menggunakan array dalam program, kita harus selalu ingat bahwa kedua kesalahan tersebut mungkin terjadi. Dari kedua kasus di atas, kesalahan indeks array keluar batas adalah kesalahan yang lebih sering terjadi.

Untuk suatu variabel array, seperti variabel lainnya, kita bisa mendeklarasikan dan mengisinya dengan satu langkah sekaligus, misalnya :

int[] daftar = new int[5];

Jika daftar merupakan variabel lokal dalam subrutin, maka perintah di atas akan persis sama dengan dua perintah :

int[] daftar;
daftar = new int[5];

(Jika daftar adalah variabel instansi, tentukan kita tidak bisa mengganti "int[] daftar = new int[5];" dengan "int[] daftar; daftar = new int[5];" karena ini hanya bisa dilakukan di dalam subrutin)

Array yang baru dibuat akan diisi dengan nilai awal yang tergantung dari tipe dasar array tersebut seperti dijelaskan sebelumnya. Akan tetapi Java juga menyediakan cara untuk memberi isi array baru dengan daftar isinya. Dalam pernyataan yang untuk membuat array, ini bisa dilakukan dengan menggunakan penginisialiasi array (array initializer), misalny :
int[] daftar = { 1, 4, 9, 16, 25, 36, 49 };

akan membuat array baru yang berisi 7 nilai, yaitu 1, 4, 9, 16, 25, 36, dan 49, dan mengisi daftar dengan referensi ke array baru tersebut. Nilai daftar[0] berisi 1, nilai daftar[1] berisi 4, dan seterusnya. Panjang daftar adalah 7, karena kita memberikan 7 nilai awal kepada array ini.

Suatu penginisialisasi array memiliki bentuk daftar angka yang dipisahkan dengan koma dan diapit dengan tanda kurung kurawal {}. Panjang array tersebut tidak perlu diberikan, karena secara implisit sudah bisa ditentukan dari jumlah daftar angkanya. Elemen di dalam penginisialisasi array tidak harus selalu berbentuk konstanta. Juga bisa merupakan variabel atau ekspresi apa saja, asalkan nilainya bertipe sama dengan tipe dasar array tersebut. Misalnya, deklarasi berikut membuat array dari delapan jenis Color beberapa warna telah dibentuk dengan ekspresi "new Color(r,g,b);"

Color[] palette =
{
Color.black,
Color.red,
Color.pink,
new Color(0,180,0), // hijau gelap
Color.green,
Color.blue,
new Color(180,180,255), // biru muda
Color.white
};

Inisialisasi array bentuk seperti ini hanya bisa digunakan dalam deklarasi suatu variabel baru, akan tetapi tidak bisa digunakan seperti operator pemberi nilai (=) di tengah-tengah suatu program. Akan tetapi ada cara lain yang bisa digunakan sebagai pernyataan pemberian nilai atau diberikan ke dalam subrutin. Yaitu menggunakan jenis lain dari operator new untuk membuat atau menginisialisasi objek array baru. (Cara ini agak kaku dengan sintaks aneh, seperti halnya sintaks kelas anonim yang telah didiskusikan sebelumnya). Misalnya untuk memberi nilai kepada suatu variabel daftar, kita bisa menggunakan :

daftar = new int[] { 1, 8, 27, 64, 125, 216, 343 };

Sintaks umum dari bentuk operator new seperti ini adalah

new TipeDasar [ ] { daftar_nilai_nilai }

Ini adalah suatu ekspresi yang isinya merupakan objek, dan bisa digunakan untuk banyak situasi di mana suatu objek dengan tipe TipeDasar dipentingkan. Misalnya buatTombol merupakan metode yang mengambil array String sebagai parameter, maka kita bisa menuliskan
buatTombol( new String[] { "Stop", "Jalan", "Berikut", "Sebelum" } );

Catatan terakhir : untuk alasan sejarah, maka deklarasi

int[] daftar;

akan bernilai sama dengan

int daftar[];

di mana sintaks tersebut digunakan dalam bahasa C dan C++. Akan tetapi sintaks alternatif ini tidak begitu masuk akan dalam Java, atau mungkin lebih baik dihindari. Lagian, maksudnya adalah mendeklarasikan variabel dengan tipe tertentu dan namanya adalah int[]. Akan lebih masuk akan untuk mengikuti siintaks "nama_tipe nama_variabel" seperti pada bentuk bertama.

Record Dengan Query

Menandai data dengan query dapat dilakukan pada view ataupun pada tabel. Menandai data dengan query pada view dapat dilakukan dengan menu Theme - Query. Sedang?kan pada tabel digunakan menu Table - Query. Anda juga dapat mengklik toobar atau Ctrl+Q. Kotak dialog berikut akan tampil.

Gambar 4.16. Data grafis dan atribut saling terkoneksi.

Pada pemilihan data lewat query, kita disuruh untuk membuat formula atau persamaan logika pada kota kosong di bagian bawah. ArcView akan mengevaluasi persamaan tersebut. Record atau objek yang memenuhi persamaan tersebut akan ditandai. Dalam membuat persamaan logika, kita dapat mengetikkan langsung persamaan tersebut, atau mengunakan field, operator, dan value yang telah disediakan.

Bila anda menuliskan formula dengan cara mengetikkan, ingat bahwa nama field harus diapit oleh kurung siku ([]) dan nilai string atau data bertipe karakter harus diapit dengan tanda petik dua ("). Sedangkan untuk data bertipe numerik tidak perlu diapit oleh tanda petik dua.

Akan lebih baik apabila anda membuat formula dengan menggunakan field, operator atau value yang telah disediakan. Untuk menggunakan field atau value yang telah ada pada daftar, klik 2 kali field atau value tersebut. Untuk tanda operator klik sekali.

Dalam prakteknya, biasanya digunakan kombinasi. Field dan operator diambil dari daftar, sementara nilai yang tidak ada pada daftar diketikkan langsung melalui keyboard. Berikut ini disajikan beberapa contoh persamaan logika.

Tabel 4.2. Contoh beberapa persamaan logika

No


Persamaan


Arti

1


( [Kabupaten] = "Kab. Bangli" )


Menandai record atau objek dimana field kabupaten sama dengan Kab. Bangli.

2


( [Total] >= 300000 )


Menandai record yang total penduduknya lebih besar atau sama dengan 300.000.

3


( ( [Perempuan] * 2 ) > [Total] )


Memilih record dimana 2 kali penduduk perempuan lebih besar dari total penduduk.

4


( [Total] > 300000 ) and ( [Rt] < 80000 )


Memilih record yang total penduduknya lebih besar dari 300.000 tetapi dengan jumlah rumah tangga lebih kecil dari 80.000.

Secara standar, ArcView akan mengkalkulasi persamaan dari kiri ke kanan. Apabila anda ingin bagian tertentu dari persamaan dikalkulasi terlebih dahulu, sisipkanlah tanda kurung buka dan kurung tutup pada bagian tersamaan tersebut.

Tanda operator And memberikan nilai benar apabila kedua ekspresi bernilai benar. Operator Or apabila salah satu ekspresi bernilai benar. Sedangkan Not Membalik keadaan, bila ekspresi benar akan bernilai salah, dan sebalikknya. Perhatikan tabel di bawah ini.

Tabel 4.3. Contoh Penggunaan operator (), And, Or, dan Not

No


Persamaan


Nilai

1


2 * 3 + 4


10

2


2 * ( 3 + 4 )


14

3


( 2 * 3 > 2 + 3 ) And ( 2 + 3 > 2 * 3)


Salah

4


( 2 * 3 > 2 + 3 ) And ( 2 + 3 < 2 * 3)


Benar

5


( 2 * 3 > 2 + 3 ) Or ( 2 + 3 > 2 * 3)


Benar

6


( 2 * 3 > 2 + 3 ) Or ( 2 + 3 < 2 * 3)


Benar

7


( 2 * 3 < 2 + 3 ) Or ( 2 + 3 > 2 * 3)


Salah

8


( Not ( 2 * 3 < 2 + 3 ) )


Benar

9


( Not ( 2 * 3 > 2 + 3 ) )


Salah

Beberapa hal yang perlu diperhatikan dalam kotak dialog Query di atas adalah :

1. Secara standar kotak cek Update Value selalu diaktifkan. Ini berarti setiap anda mengklik daftar field yang ada di bagian kiri, seluruh nilai field yang ada pada tabel tersebut akan ditampilkan pada kotak Value. Sedangkan bila tidak diaktifkan perubahan field yang dipilih pada kotak Fields, tidak akan merubah nilai pada kotak value.

2. New Set, berarti kita membuat pilihan baru dari ekspresi atau persamaan yang dibuat. Bila sebelumnya ada satu atau beberapa record yang telah dipilih akan di-unselect terlebih dahulu.

3. Add To Set, Hasil pemilihan record dari persamaan yang dibuat, akan ditambahkan pada record yang telah terpilih sebelumnya. Contoh bila semula ada 5 record yang terpilih dan persamaan yang dibuat memenuhi 3 kreteria selain record yang telah terpilih, maka sekarang akan ada 8 record yang ditandai,

4. Select From Set, Pemilihan record bukan dilakukan pada semua record dalam tabel, tetapi hanya dari record yang telah dipilih. Cara ini biasanya digunakan untuk mempersempit pilihan dengan membuat beberapa persamaan. Contoh bila semula ada 10 record yang ditandai, dan bila persamaan yang dibuat memenuhi 12 kriteria dari seluruh record dalam tabel dan 4 kriteria dari record yang terpilih, maka sekarang akan ada 4 record yang ditandai.

Bila jumlah record cukup banyak anda dapat menggunakan fasilitas Find untuk mencari data bertipe string dalam tabel dan langsung menandai record yang ditemukan. Gunakan menu Table - Find atau klik toolbar atau Ctrl+F. Bila muncul kotak dialog berikut, ketik teks yang akan dicari.

Kamis, 04 Maret 2010

Array Multi Dimensi

Tipe apapun bisa digunakan sebagai tipe dasar suatu array. Kita bisa membuat array int, array String, array Object dan seterusnya. Terutama, karena array adalah tipe Java kelas satu, kita bisa membuat array yang bertipe array.

Misalnya suatu array bertipe int[], juga otomatis memiliki array bertipe int[][], yaitu "array bertipe array int". Array tersebut disebut array 2 dimensi. Tentunya, dengan tipe int[][], kita juag bisa membuat arraynya dengan tipe int[][][], yang merupakan array 3 dimensi, dan seterusnya. Tidak ada batasan berapa dimensi array yang kita buat, akan tetapi bukan sesuatu yang biasa dilakukan untuk membuat array lebih dari 3 dimensi. Pembahasan kita akan lebih dikhususkan pada array 2 dimensi. Tipe TipeDasar[][] biasanya dibaca "array 2 dimensi bertipe TipeDasar" atau "array dari array TipeDasar".

Deklarasi pernyataan "int[][] A;" adalah membuat variabel bernama A dengan tipe int[][]. Variabel ini berisi objek yang bertipe int[][]. Pernyataan pemberian nilai "A = new int[3][4];" akan membuat objek array 2 dimensi dan mengisi A ke objek yang baru dibuat tersebut.

Seperti biasa, deklarasi dan pemberian nilai bisa digabung menjadi satu pernyataan, seperti "int[][] A = new int[3][4];". Objek yang baru dibuat adalah objek yang merupakan array dari array int. Bagian int[3][4] menyatakan bahwa ada 3 array int di dalam array A, dan di setiap array int tersebut terdapat 4 int.

Cara seperti itu mungkin sedikit membingungkan, akan tetapi akan lebih mudah apabila kita bayangkan array tersebut seperti matriks. Istilah "int[3][4]" bisa disebut sebagai matriks dengan 3 baris dan 4 kolom, seperti pada ilustrasi berikut ini :



Untuk banyak hal, kita bisa mengabaikan kenyataan di atas, dan membayangkan bentuk matriks seperti di atas. Kadang-kadang kita juga harus ingat bahwa setiap baris sebenarnya juga merupakan suatu array. Array-array ini bisa dirujuk dengan A[0], A[1], dan A[2]. Setiap baris bertipe int[].

Pernyataan A[1] merujuk pada salah satu baris pada array A. Karena A[1] itu sendiri sebenarnya adalah array int, kita bisa menambah indeks lain untuk merujuk pada posisi pada baris tersebut. Misalnya A[1][3] adalah elemen nomor 3 pada baris 1. Seperti biasa, ingat bahwa posisi baris dan kolom dimulai dari 0. Jadi pada contoh di atas, A[1][3] bernilai 5. Lebih umum lagi, A[i][j] adalah posisi pada baris i dan kolom j. Seluruh elemen pada A bisa dinamakan seperti berikut :

A[0][0] A[0][1] A[0][2] A[0][3]
A[1][0] A[1][1] A[1][2] A[1][3]
A[2][0] A[2][1] A[2][2] A[2][3]

A[i][j] adalah variabel bertipe int. Kita bisa mengisi nilainya atau menggunakannya seperti variabel bertipe int biasa.

Perlu juga diketahui bahwa A.length akan memberikan jumlah baris pada A. Untuk mendapatkan jumlah kolom pada A, kita harus mencari jumlah int dalam setiap baris, yaitu yang disimpan pada A[0]. Jumlah kolom ini bisa didapatkan dengan menggunakan A[0].length, atau A[1].length atau A[2].length. (Tidak ada aturan baku yang menyatakan bahwa pada setiap baris suatu array harus memiliki panjang yang sama, dan sebenarnya pada beberapa aplikasi, juga digunakan array dengan panjang yang berbeda-beda pada setiap barisnya. Akan tetapi apabila kita membuat array dengan perintah seperti di atas, maka kita akan selalu mendapatkan array dengan panjang array yang sama.)

Array 3 dimensi juga dibuat dan diolah dengan cara yang sama. Misalnya, array 3 dimensi bertipe int bisa dibuat dengan pernyataan "int[][][] B = new int [7][5][11];". Kita juga bisa mengilustrasikannya sebagai kubus 3-dimensi. Masing-masing bloknya bertipe int yang bisa dipanggil dalam bentuk B[i][j][k]. Array dimensi lain yang lebih tinggi juga mengikuti pola yang sama, akan tetapi akan sangat sulit untuk membuat visualisasi struktur arraynya.

Kita bisa mengisi array multi dimensi sekaligus pada saat dideklarasikan. Ingat sebelumnya bagaimana array 1 dimensi biasa dideklarasikan, dan bagaimana isinya diinisialisasikan, yaitu seperti daftar nilai-nilainya yang dipisahkan dengan koma, dan diletakkan di dalam tanda kurung kurawal { dan }.

Inisialisasi array bisa juga digunakan untuk array multi dimensi, yang terdiri dari beberapa inisialisasi array 1 dimensi, masing-masing untuk setiap barisnya. Misalnya, array A pada gambar di atas dapat dibuat dengan perintah :

int[][] A = { { 1, 0, 12, -1 },
{ 7, -3, 2, 5 },
{ -5, -2, 2, 9 }
};

Jika tidak ada inisialisasi yang diberikan untuk suatu array, maka nilainya akan diisi dengan nilai awal tergantung pada tipenya : nol untuk bilangan, false untuk boolean dan null untuk objek.

Seperti halnya array 1 dimensi, array 2 dimensi juga sering diolah dengan menggunakan perulangan for. UNtuk mengolah semua elemen pada array 2 dimensi, kita bisa menggunakan pernyataan for bertingkat. Jika array A dideklarasikan seperti

int[][] A = new int[3][4];

maka kita bisa mengisi 0 untuk semua elemen pada A dengan menggunakan

for (int baris = 0; baris < 3; baris++) {
for (int kolom = 0; kolom < 4; kolom++) {
A[baris][kolom] = 0;
}
}

Pertama kali perulangan for bagian luar akan memproses dengan baris = 0. Bagian dalamnya akan mengisi keempat kolom pada baris pertama, yaitu A[0][0] = 0, A[0][1] = 0, A[0][2] = 0, dan A[0][3] = 0. Kemudian perulangan for bagian luar akan mengisi baris kedua, dan seterusnya.

Dan juga, kita bisa menjumlah semua elemen pada A dengan

int jml = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; i++)
jml = jml + A[i][j];

Untuk mengolah array 3 dimensi, tentunya kita harus menggunakan perulangan for bertingkat 3.

Suatu array 2 dimensi bisa digunakan untuk menyimpan data yang secara alami memang tersusun sebagai baris dan kolom. Misalnya papan catur terdiri dari 8 baris dan 8 kolom. Jika suatu kelas dinamakan PapanCatur untuk merepresentasikan papan catur, maka kita bisa deklarasikan dengan perintah

PapanCatur[][] papan = new PapanCatur[8][8];

Kadang-kadang array 2 dimensi juga digunakan untuk masalah yang tidak terlalu jelas matriksnya. Misalnya perusahaan yang memiliki 25 toko. Anggap masing-masing toko memiliki keuntungan yang didapat pada masing-masing toko tersebut setiap bulan pada tahun 2009. Jika toko-toko tersebut memiliki nomor 0 hingga 24, dan 12 bulan dari Januari 09 hingga Desember 09 dinomori 0 hingga 11, maka data keuntungan dapat disimpan dalam array untung yang dideklarasikan seperti :

double[][] untung = new double[25][12];

untung[3][2] adalah keuntungan yang dibuat oleh toko nomor 3 di bulan Maret. Atau secara umum, untung[noToko][noBulan] adalah keuntungan toko noToko pada bulan noBulan. Dalam contoh ini array 1 dimensi untung[noToko] memiliki arti : Data keuntungan satu toko selama satu tahun.

Anggap array untung telah diisi dengan data. Data ini bisa diolah lebih lanjut. Misalnya, total keuntungan seluruh perusahaan -- sepanjang tahun dari seluruh toko -- dapat dihitung dengan menjumlahkan semua elemen pada array :

double totalUntung; // Total keuntungan perusahaan tahun 2009

totalUntung = 0;
for (int toko = 0; toko < 25; toko++) {
for (int bulan = 0; bulan < 12; bulan++)
totalUntung += untung[toko][bulan];
}

Kadang-kadang kita juga perlu menghitung hanya satu baris atau satu kolom saja, bukan keseluruhan array. Misalnya, kita ingin menghitung keuntungan total perusahaan pada bulan Desember, yaitu bulan nomor 11, maka kita bisa gunakan perulangan :

double untungDesember = 0.0;
for (noToko = 0; noToko < 25; noToko++)
untungDesember += untung[noToko][11];

Sekarang mari kita buat array 1 dimensi yang berisi total keuntungan seluruh toko setiap bulan :

double[] untungBulanan; // Keuntungan setiap bulan
untungBulanan = new double[12];

for (int bulan = 0; bulan < 12; bulan++) {
// hitung total keuntungan semua toko bulan ini
untungBulanan[bulan] = 0.0;
for (int toko = 0; toko < 25; toko++) {
untungBulanan[bulan] += profit[toko][bulan];
}
}

Sebagai contoh terakhir untuk mengolah array keuntungan, misalnya kita ingin tahu toko mana yang menghasilkan keuntungan terbesar sepanjang tahun. Untuk menghitungnya, kita harus menjumlahkan keuntungan setiap toko sepanjang tahun. Dalam istilah array, ini berarti kita ingin mengetahui jumlah setiap baris pada array. Kita perlu mencatat hasil perhitungannya untuk mencari mana toko dengan keuntungan terbesar.

double untungMaks; // Keuntungan terbesar suatu toko
int tokoTerbaik; // Nomor toko yang memiliki keuntungan terbesar

double total = 0.0; // Total keuntungan suatu toko

// Pertama-tama hitung keuntungan dari toko nomo 0

for (int bulan = 0; bulan < 12; bulan++)
total += untung[0][bulan];

tokoTerbaik = 0; // Mulai dengan anggapan toko nomor 0
untungMaks = total; // adalah toko paling menguntungkan

// Sekarang kita lihat seluruh toko, dan setiap kali
// kita melihat toko dengan keuntungan lebih besar dari
// untungMaks, kita ganti untungMaks dan tokoTerbaik
// dengan toko tersebut

for (toko = 1; toko < 25; toko++) {

// Hitung keuntungan toko tersebut sepanjang tahun
total = 0.0;
for (bulan = 0; bulan < 12; bulan++)
total += untung[toko][bulan];

// Bandingkan keuntungan toko ini dengan untungMaks
if (total > untungMaks) {
untungMaks = total; // keuntungan terbesar saat ini
tokoTerbaik = toko; // datang dari toko ini
}

} // akhir for

// Di sini, untungMaks adalah keuntungan terbesar dari 25 toko
// dan tokoTerbaik adalah toko dengan keuntung tersebut
// (Mungkin juga ada toko yang menghasilkan keuntungan
// yang persis sama.)

Array Liast Dan Vector

ArrayList

Kelas ArrayDinamisInt bisa digunakan jika kita membutuhkan array dengan batas maksimum yang tak terbatas. Akan tetapi jika kita ingin menyimpan BentukGeometri misalnya, kita harus membuat kelas baru. Kelas tersebut mungkin bernama ArrayDinamisBentukGeometri, dan akan tampak sama persis dengan ArrayDinamisInt dengan beberapa perubahan di mana "int" muncul akan diganti dengan "BentukGeometri". Juga demikian jika kita ingin membuat kelas ArrayDinamisDouble, ArrayDinamisPemain, dan sebagainya.

Yang agak sedikit lucu adalah kelas tersebut sangat mirip isinya, hanya kelas-kelasnya saja yang berlainan. Akan sangat lebih baik apabila kita bisa membuat kelas umum yang berlaku untuk semua kelas. Hal ini disebut dengan pemrograman generik. Beberapa bahasa pemrograman seperti C++ memiliki fasilitas untuk melakukan pemrograman generik. Java tidak memiliki fasilitas seperti itu (maksudnya tidak sama persis). Tapi kita bisa membuat sesuatu yang mirip dengan itu pada Java dengan menggunakan struktur data yang memiliki tipe "Object".

Pada Java, setiap kelas adalah kelas turunan dari kelas yang bernama Object. Artinya setiap objek dapat dirujuk oleh variabel bertiipe Object. Semua objek dapat dimasukkan dalam array bertipe Object[]. Jika suatu subrutin memiliki parameter formal bertipe Object, maka objek apapun bisa diberikan kepada subrutin tersebut.

Jika kita buat kelas ArrayDinamisObject, maka kita bisa menyimpan objek apapun. Ini sebenarnya bukan programming generik sebenarnya, dan tidak berlaku untuk tipe primitif seperti int dan double. Sebenarnya, kita tidak perlu membuat kelas ArrayDinamisObject sendiri, karena Java telah memiliki kelas standar yang dinamakan ArrayList yang sifatnya mirip dengan yang kita sebutkan sebelumnya.

ArrayList disimpan dalam paket java.util, jadi jika kita ingin menggunakan kelas ArrayList dalam sebuat program, kita harus memberikan "import java.util.ArrayList;" atau "import java.util.*;" di awal program kita.

Kelas ArrayList berbeda dengan kelas ArrayDinamisInt dalam arti, objek ArrayList selalu memiliki ukuran tertentu, dan kita tidak boleh mengambil posisi di luar ukuran ArrayList. Dalam hal ini, ArrayList mirip seperti array biasa. Akan tetapi, ukuran ArrayList bisa bertambah kapan saja jika diperlukan. Kelas ArrayList memiliki banyak metode instansi. Kita akan jelaskan sebagian yang sangat berguna. Misalnya daftar adalah variabel dengan tipe ArrayList.

* daftar.size() -- Fungsi ini menghasilkan ukuran ArrayList saat ini. Posisi valid dalam daftar adalah yang bernomor 0 hingga daftar.size() - 1. Ingat bahwa ukurannya bisa nol. Panggilan konstruktor new ArrayList() akan membuat ArrayList dengan ukuran nol.
* daftar.add(obj) -- Menambah objek di akhir ArrayList, kemudian menambah ukurannya dengan 1. Parameter obj merujuk pada objek dengan tipe apapun, atau bisa bernilai null.
* daftar.get(N) -- Mengambil nilai yang disimpan pada posisi N pada ArrayList. N harus bertipe bilangan bulat antara 0 hingga daftar.size() - 1. Jika N berada di luar rentang ini, pesan kesalahan akan ditampilkan. Memanggil fungsi ini mirip dengan memanggil array seperti A[N] untuk suatu array A. Akan tetapi kita tidak bisa menggunakan daftar.get(N) pada ekspresi di sebelah kiri daftar.get(N) = 5 tidak boleh dilakukan)
* daftar.set(N, obj) -- Mengisi suatu objek obj di posisi N dari suatu ArrayList, dan mengganti apapun yang sudah disimpan sebelumnya pada posisi N. Bilangan bulat N harus berada pada rentang 0 hingga daftar.size() - 1. Perintah ini mirip dengan perintah A[N] = obj pada array A.
* daftar.remove(obj) -- Jika objek tersebut ada di dalam ArrayList, maka objek tersebut akan dibuang. Elemen lain setelah posisi objek tersebut di dalam ArrayList akan digeser satu posisi. Kemudian ukuran ArrayList akan berkurang 1. Jika obj terdapat dalam ArrayList lebih dari satu kali, hanya yang pertama saja yang dibuang.
* daftar.remove(N) -- Untuk bilangan bulat N, maka perintah ini akan menghapus posisi ke-N pada ArrayList. N harus berada pada rentang 0 hingga daftar.size() - 1. Elemen setelah ini akan digeser satu posisi. Kemudian ukuran ArrayList berkurang 1.
* daftar.indexOf(obj) -- Fungsi untuk mencari suatu objek obj di dalam ArrayList. Jika objek ditemukan, maka posisinya di dalam ArrayList akan dikembalikan. Jika tidak, maka fungsi ini akan mengembalikan -1.

Misalnya,kita akan membuat pemain dalam game yang digambarkan dengan objek dengan tipe Pemain. Pemain yang berada dalam game disimpan dalam ArrayList bernama paraPemain. Variabel ini dideklarasikan seperti :

ArrayList paraPemain;

dan kita inisialisasikan dengan objek kosong dengan perintah

paraPemain = new ArrayList();

Jika pemainBaru adalah variabel yang bertipe Pemain, maka pemain baru tersebut bisa ditambahkan ke dalam ArrayList dan ke dalam game dengan perintah :

paraPemain.add(pemainBaru);

dan jika pemain nomor i keluar dari game, maka kita hanya perlu memberikan perintah

paraPemain.remove(i);

Atau jika pemain adalah objek bertipe Pemain yang akan kita keluarkan dari game, maka kita bisa menggunakan perintah

paraPemain.remove(pemain);

Semuanya terlihat sangat mudah. Satu-satunya kesulitan yang akan kita temui adalah ketika kita ingin mengambil nilai yang disimpan pada posisi i di dalam ArrayList. Tipe keluaran fungsi ini adalah Object. Dalam hal ini objek yang diambil oleh fungsi ini sebenarnya bertipe Pemain. Supaya kita bisa menggunakan hasil keluarannya, maka kita perlu menggunakan casting tipe untuk mengubahnya menjadi tipe Player, dengan cara :

Pemain pmn = (Pemain)paraPemain.get(i);

Misalnya, jika kelas Pemain memiliki metode instansi yang dinamakan jalan() yang dipanggil ketika seorang pemain menjalankan dadu atau kartu, maka kita bisa menuliskan kode untuk memberi giliran kepada semua pemain untuk jalan, yaitu dengan

for (int i = 0; i < paraPemain.size(); i++) {
Pemain pmn = (Pemain)paraPemain.get(i);
pmn.jalan();
}

Dua baris di dalam perulangan for tersebut dapat digabungkan dengan satu perintah :

((Pemain)paraPemain.get(i)).jalan();

Perintah ini akan mengambil elemen pada ArrayList mengcasting tipenya, kemudian memanggil metode jalan() pada pemain yang baru diambil tersebut. Tanda kurung di sekitar "(Pemain)paraPemain.get(i)" diperlukan karena aturan dalam Java sehingga perintah dalam kurung akan dijalankan terlebih dahulu sebelum metode jalan() dipanggil.

Vector

Kelas ArrayList diperkenalkan pada Java versi 1.2, sebagai salah satu kumpulan kelas yang digunakan untuk bekerja dengan sekumpulan koleksi objek. Jika akan bahas lebih lanjut tentang "kelas koleksi" pada bagian berikutnya. Versi awal Java tidak memiliki ArrayList, akan tetapi memiliki kelas yang sangat mirip yaitu java.util.Vector. Kita masih bisa melihat Vector digunakan pada program lama, dan dalam beberapa kelas standar Java, sehingga kita perlu tahu tentang kelas ini.

Menggunakan Vector mirip dengan menggunakan ArrayList. Perbedaannya adalah nama metode yang berbeda untuk melakukan tugas yang sama, atau nama metode yang berbeda untuk melakukan tugas yang sama.

Seperti ArrayList, suatu Vector mirip dengan array Object yang bisa berkembang jika diperlukan. Konstruktor new Vector() membuat vektor tanpa elemen.

Misalnya vec adalah suatu Vector. Maka :

* vec.size() adalah fungsi untuk mengembalikan jumlah elemen di dalam vektor.
* vec.addElement(obj) akan menambahkan Object obj di akhir vektor. Sama dengan metode add() pada ArrayList.
* vec.removeElement(obj) menghapus obj dari dalam vektor, kalau ada. Hanya objek pertama yang ditemui akan dihapus. Sama dengan remove(obj) pada kelas ArrayList
* vec.removeElementAt(N) menghapus elemen ke-N. N harus berada pada rentang 0 hingga vec.size() - 1. Sama dengan remove(N) pada ArrayList
* vec.setSize(N) akan mengubah ukuran vektor menjadi N. Jika di dalam vektor terdapat elemen yang jumlahnya lebih banyak dari N, maka elemen lainnya akan dihapus. Jika lebih sedikit, maka tempat kosong akan diisi dengan null. Kelas ArrayList tidak memiliki metode seperti ini.

Kelas Vector memiiki banyak metode lagi, akan tetapi ini adalah metode yang sering digunakan.

Membuat Dan Menggunakan Array

Jika sekumpulan data digabungkan dalam satu unit, hasilnya adalah suatu struktur data. Data struktur dapat berupa struktur yang sangat kompleks, akan tetapi dalam banyak aplikasi, data struktur yang cocok hanya terdiri dari kumpulan data berurutan. Struktur data sederhana seperti ini bisa berupa array atau record.

Istilah "record" sebetulnya tidak digunakan pada Java. Suatu record pada intinya mirip dengan objek pada Java yang hanya memiliki variabel instansi tanpa metode instansi. Beberapa bahasa pemrograman lain yang tidak mendukung objek biasanya mendukung record. Dalam bahasa C yang bukan bahasa berorientasi objek, misalnya, memiliki tipe data record, dimana pada C disebut "struct". Data pada record -- dalam Java, adalah variabel instansi suatu objek -- disebut field suatu record. Masing-masing item disebut nama field. Dalam Java, nama field adalah nama variabel instansi. Perbedaan sifat dari suatu record adalah bahwa item pada record dipanggil berdasarkan namanya, dan field yang berbeda dapat berupa tipe yang berbeda. Misalnya, kelas Orang didefisikan sebagai :

class Orang {
String nama;
int nomorID;
Date tanggalLahir;
int umur;
}

maka objek dari kelas Orang bisa disebut juga sebagai record dengan 4 field. Nama fieldnya adalah nama, nomorID, tanggalLahir dan umur. Lihat bahwa tipe datanya berbeda-beda yaitu String, int, dan Date.

Karena record hanya merupakan bagian lebih kecil dari objek, kita tidak akan bahas lebih lanjut di sini.

Seperti record, suatu array adalah kumpulan item. Akan tetapi, item pada record dipanggil dengan nama, sedangkan item pada array dinomori, dan masing-masing item dipanggil besarkan nomor posisi pada array tersebut. Semua item pada array harus bertipe sama. Definisi suatu array adalah : kumpulan item bernomor yang semuanya bertipe sama. Jumlah item dalam suatu array disebut panjang array. Nomor posisi dari array disebut indeks item tersebut dalam array. Tipe dari item tersebut disebut tipe dasar dari array.

Tipe dasar suatu array bisa berupa tipe Java apa saja, baik berupa tipe primitif, nama kelas, atau nama interface. Jika tipe dasar suatu array adalah int, maka array tersebut disebut "array int". Suatu array bertipe String disebut "array String". Akan tetapi array bukan urutan int atau urutan String atau urutan nilai bertipe apapun. Lebih baik jika array adalah urutan variabel bertipe int atau String atau tipe lainnya.

Seperti biasa, ada dua kemungkinan kegunaan variabel : sebagai nama suatu lokasi di memori, dan nama suatu nilai yang disimpan pada lokasi memori. Setiap posisi pada array bersifat seperti variabel. Setiap posisi dapat menyimpan nilai dengan tipe tertentu (yaitu tipe dasar array). Isinya bisa diganti kapanpun. Nilai tersebut disimpan di dalam array. Array merupakan kontainer bukan kumpulan nilai.

Item pada array (maksudnya setiap anggota variabel dalam array tersebut) sering juga disebut elemen array. Dalam Java, elemen array selalu dinomori mulai dari nol. Yaitu, indeks dari elemen pertama suatu array adalah nol. Jika panjang array adalah N, maka indeks elemen terakhir adalah N-1. Sekali array dibuat, maka panjangnya tidak bisa diubah lagi.

Dalam Java, array adalah objek. Ada beberapa konsekuensi yang lahir dari fakta ini. Array harus dibuat dengan operator new. Variabel tidak bisa menyimpan array; variabel hanya bisa merujuk pada array. Variabel lain yang bisa merujuk array juga bisa bernilai null yang berarti ia tidak merujuk pada lokasi memori apapun. Seperti objek lain, array juga bagian dari suatu kelas, di mana seperti kelas lain adalah kelas turunan dari kelas Object. Elemen array pada dasarnya adalah variabel instansi dalam objek array, kecuali mereka dipanggil dalam indeksnya bukan namanya.

Meskipun array berupa objek, ada beberapa perbedaan antara array dan objek lainnya, dan ada beberapa fitur khusus Java untuk membuat dan menggunakan array.

Misalnya A adalah variabel yang merujuk pada suatu array. Maka indeks k di dalam A bisa dipanggil dengan A[k]. Item pertama adalah A[0], yang kedua adalah A[i], dan seterusnya. A[k] adalah suatu variabel dan bisa digunakan seperti variabel lainnya. Kita bisa memberinya nilai, bisa menggunakannya dalam ekspresi, dan bisa diberikan sebagai parameter pada subrutin. Semuanya akan didiskusikan di bawah nanti. Untuk sekarang ingat sintaks berikut

variabel_array [ekspresi_integer]

untuk merujuk pada suatu array.

Meskipun setiap array merupakan suatu objek, kelas array tidak harus didefinisikan sebelumnya. Jika suatu tipe telah ada, maka kelas array dari tipe tersebut otomatis ada. Jika nama suatu tipe adalah TipeDasar, maka nama kelas arraynya adalah TipeDasar[]. Artinya, suatu objek yang diciptakan dari kelas TipeDasar[] adalah array dari item yang tiap itemnya bertipe TipeDasar. Tanda kurung "[]" dimaksudkan untuk mengingat sintaks untuk mengambil item di dalam suatu array. "TipeDasar[]" dibaca seperti "array TipeDasar". Mungkin perlu juga dijelaskan bahwa jika KelasA adalah kelas turunan dari KelasB maka KelasA[] otomatis menjadi kelas turunan KelasB[].

Tipe dasar suatu array dapat berupa tipe apapun yang ada atau sudah didefinisikan pada Java. Misalnya tipe primitif int akan diturunkan kelas array int[]. Setiap elemen di dalam array int[] adalah variabel yang memiliki tipe int dan bisa diisi dengan nilai dengan tipe int. Dari kelas yang bernama String diturunkan tipe array String[]. Setiap elemen di dalam array String[] adalah variabel dengan tipe String, yang bisa diisi dengan nilai bertipe String. Nilai ini bisa null atau referensi ke objek yang bertipe String (dan juga kelas turunan dari String)

Mari kita lihat contoh lebih konkrotnya menggunakan array bilangan bulat sebagai contoh pertama kita. Karena int[] adalah sebuah kelas, maka kita bisa menggunakannya untuk mendeklarasikan variabel. Misalnya,

int[] daftar;

yang membuat variabel bernama daftar dengan tipe int[]. Variabel ini bisa menunjuk pada array int, akan tetapi nilai awalnya adalah null (jika merupakan variabel anggota suatu kelas) atau tak tentu (jika merupakan variabel lokal di dalam suatu metode). Operator new digunakan untuk membuat objek array baru, ayng kemudian bisa diberikan kepada daftar. Sintaksnya sama seperti sintaks sebelumnya, yaitu :

daftar = new int[5];

membuat array 5 buah integer. Lebih umum lagi, konstruktor "new TipeDasar[N]" digunakan untuk membuat array bertipe TipeDasar[]. Nilai N di dalam kurung menyatakan panjang array, atau jumlah elemen yang bisa ditampung. Panjang array adalah variabel instansi di dalam objek array, sehingga array tahu berapa panjangnya. Kita bisa mendapatkan panjang suatu array, misalnya daftar menggunakan daftar.length (akan tetapi kita tidak bisa mengubahnya)

Hasil dari pernyataan "daftar = new int[5];" dapat diilustrasikan sebagai berikut

Ilustrasi array int

Perlu dicatat bahwa array integer secara otomatis diisi dengan nol. Dalam Java, array yang baru dibuat akan selalu diisi dengan nilai tertentu: nol untuk angka, false untuk boolean, karakter dengan nilai Unicode 0 untuk char dan null untuk objek.

Elemen di dalam array daftar dapat dirujuk dengan daftar[0], daftar[1], daftar[2], daftar[3], dan daftar[4] (ingat juga bahwa nilai indeks terbesar adalah panjangnya array dikurang satu). Akan tetapi, referensi array sebetulnya lebih umum lagi. Tanda kurung di dalam referensi array bisa berisi ekspresi apapun yang nilainya suatu integer. Misalnya jika idks adalah variabel bertipe int, maka daftar[idks] dan daftar[2*idks+3] secara sintaks benar.

Contoh berikut akan mencetak semua isi integer di dalam array daftar ke layar :

for (int i = 0; i < daftar.length; i++) {
System.out.println( daftar[i] );
}

Perulangan pertama adalah ketika i = 0, dan daftar[i] merujuk pada daftar[0]. Jadi nilai yang disimpan pada variabel daftar[0] akan dicetak ke layar. Perulangan kedua adalah i = 1, sehingga nilai daftar[i] dicetak. Perulangan berhenti setelah mencetak daftar[4] dan i menjadi sama dengan 5, sehingga kondisi lanjutan "i < daftar.length" tidak lagi benar. Ini adalah contoh umum dari menggunakan perulangan untuk mengolah suatu array.

Penggunaan suatu variabel dalam suatu program menyatakan lokasi di memori. Pikirkan sesaat tentang apa yang akan komputer lakukan ketika ia menemukan referensi ke elemen suatu array daftar[k] ketika program berjalan. Komputer harus menentukan lokasi memori di mana ia dijadikan referensi. Untuk komputer, daftar[k] berarti : "Ambil pointer yang disimpan di dalam variabel daftar. Ikuti pointer ini untuk mencari objek array. Ambil nilai k. Pergi ke posisi ke-k dari array tersebut, dan di sanalah alamat memori yang Anda ingin."

Ada dua hal yang bisa salah di sini. Misalnya nilai daftar adalah null. Dalam kasus ini, maka daftar tidak memiliki referensi sama sekali. Percobaan merujuk suatu elemen pada suatu array kosong adalah suatu kesalahan. Kasus ini akan menampilkan pesan kesalahan "pointer kosong". Kemungkinan kesalahan kedua adalah jika daftar merujuk pada suatu array, akan tetapi k berada di luar rentang indeks yang legal. Ini akan terjadi jika k < 0 atau jika k >= daftar.length. Kasus ini disebut kesalahan "indeks array keluar batas". Ketika kita menggunakan array dalam program, kita harus selalu ingat bahwa kedua kesalahan tersebut mungkin terjadi. Dari kedua kasus di atas, kesalahan indeks array keluar batas adalah kesalahan yang lebih sering terjadi.

Untuk suatu variabel array, seperti variabel lainnya, kita bisa mendeklarasikan dan mengisinya dengan satu langkah sekaligus, misalnya :

int[] daftar = new int[5];

Jika daftar merupakan variabel lokal dalam subrutin, maka perintah di atas akan persis sama dengan dua perintah :

int[] daftar;
daftar = new int[5];

(Jika daftar adalah variabel instansi, tentukan kita tidak bisa mengganti "int[] daftar = new int[5];" dengan "int[] daftar; daftar = new int[5];" karena ini hanya bisa dilakukan di dalam subrutin)

Array yang baru dibuat akan diisi dengan nilai awal yang tergantung dari tipe dasar array tersebut seperti dijelaskan sebelumnya. Akan tetapi Java juga menyediakan cara untuk memberi isi array baru dengan daftar isinya. Dalam pernyataan yang untuk membuat array, ini bisa dilakukan dengan menggunakan penginisialiasi array (array initializer), misalny :
int[] daftar = { 1, 4, 9, 16, 25, 36, 49 };

akan membuat array baru yang berisi 7 nilai, yaitu 1, 4, 9, 16, 25, 36, dan 49, dan mengisi daftar dengan referensi ke array baru tersebut. Nilai daftar[0] berisi 1, nilai daftar[1] berisi 4, dan seterusnya. Panjang daftar adalah 7, karena kita memberikan 7 nilai awal kepada array ini.

Suatu penginisialisasi array memiliki bentuk daftar angka yang dipisahkan dengan koma dan diapit dengan tanda kurung kurawal {}. Panjang array tersebut tidak perlu diberikan, karena secara implisit sudah bisa ditentukan dari jumlah daftar angkanya. Elemen di dalam penginisialisasi array tidak harus selalu berbentuk konstanta. Juga bisa merupakan variabel atau ekspresi apa saja, asalkan nilainya bertipe sama dengan tipe dasar array tersebut. Misalnya, deklarasi berikut membuat array dari delapan jenis Color beberapa warna telah dibentuk dengan ekspresi "new Color(r,g,b);"

Color[] palette =
{
Color.black,
Color.red,
Color.pink,
new Color(0,180,0), // hijau gelap
Color.green,
Color.blue,
new Color(180,180,255), // biru muda
Color.white
};

Inisialisasi array bentuk seperti ini hanya bisa digunakan dalam deklarasi suatu variabel baru, akan tetapi tidak bisa digunakan seperti operator pemberi nilai (=) di tengah-tengah suatu program. Akan tetapi ada cara lain yang bisa digunakan sebagai pernyataan pemberian nilai atau diberikan ke dalam subrutin. Yaitu menggunakan jenis lain dari operator new untuk membuat atau menginisialisasi objek array baru. (Cara ini agak kaku dengan sintaks aneh, seperti halnya sintaks kelas anonim yang telah didiskusikan sebelumnya). Misalnya untuk memberi nilai kepada suatu variabel daftar, kita bisa menggunakan :

daftar = new int[] { 1, 8, 27, 64, 125, 216, 343 };

Sintaks umum dari bentuk operator new seperti ini adalah

new TipeDasar [ ] { daftar_nilai_nilai }

Ini adalah suatu ekspresi yang isinya merupakan objek, dan bisa digunakan untuk banyak situasi di mana suatu objek dengan tipe TipeDasar dipentingkan. Misalnya buatTombol merupakan metode yang mengambil array String sebagai parameter, maka kita bisa menuliskan
buatTombol( new String[] { "Stop", "Jalan", "Berikut", "Sebelum" } );

Catatan terakhir : untuk alasan sejarah, maka deklarasi

int[] daftar;

akan bernilai sama dengan

int daftar[];

di mana sintaks tersebut digunakan dalam bahasa C dan C++. Akan tetapi sintaks alternatif ini tidak begitu masuk akan dalam Java, atau mungkin lebih baik dihindari. Lagian, maksudnya adalah mendeklarasikan variabel dengan tipe tertentu dan namanya adalah int[]. Akan lebih masuk akan untuk mengikuti siintaks "nama_tipe nama_variabel" seperti pada bentuk bertama.

Selasa, 02 Maret 2010

Array Dan Record

Array Berdimensi Satu dan Array Berdimensi Banyak

Array merupakan bagian dasar, yang disebut blok, guna keperluan pembentukan suatu struktur data lain yang lebih kompleks. Hampir setiap jenis struktur data kompleks dapat disajikan secara logik oleh array.

Kita dapat mendefinisikan array sebagai suatu himpunan hingga elemen, terurut dan
homogen. Terurut, kita artikan bahwa elemen tersebut dapat diidentifikasi sebagai elemen pertama, elemen kedua, dan seterusnya sampai elemen ke-n. Sedangkan pengertian elemen yang homogen adalah bahwa setiap elemen dari sebuah array tertentu haruslah mempunyai tipe data yang sama.

Jadi suatu array dapat mempunyai elemen semuanya berupa integer atau dapat pula
seluruhnya berupa untai aksara atau string Bahkan dapat pula terjadi bahwa suatu array mempunyai elemen berupa array pula.

Sebenarnya, pengertian array telah banyak kita kenal, dan kita pelajari dalam matematika. Di sana, array lebih terkenal sebagai matriks. Kadang-kadang ia disebut juga sebagai tabel. Juga pernah kita dengar tentang vektor. Vektor adalah bentuk yang paling sederhana dari array. Vektor merupakan array dimensi satu atau one dimensional array

- ARRAY DIMENSI SATU

Sebuah array dimensi satu, yang misalnya kita beri nama NILAI

Nilai(1) Nilai(2) Nilai(3) - - - Nilai(n)

Subscript atau indeks dari elemen array menyatakan posisi, elemen pada urutan dalam
array tersebut. Notasi yang digunakan bagi elemen array, biasanya adalah nama array
dilengkapi dengan subcript.

Secara umum, suatu array dimensi satu A dengan tipe data T dan subscript bergerak
dari L sampai dengan U, ditulis sebagai A(L:U) = (A(l)), I = L, L+1, L+2,..., U, dan setiap elemen A(l) bertipe data T.

Sebagai contoh, kita dapat menuliskan data hasil pencatatan suhu suatu ruangan setiap
satu jam selama periode 24 jam, dalam sebuah array dimensi satu. Harga minimum dari subscript dari array disebut batas bawah atau lower bound, sedangkan harga maksimumnya disebut batas atas atau upper bound. Jadi pada array di atas, L merupakan batas bawah, dan U batas atas. Sedangkan untuk array ''suhu'' yang elemennya dapat kita tulis sebagai SUHU(I), batas bawahnya adalah 1 dan batas atasnya 24. SUHU(I) menyatakan suhu pada jam ke-1, dan I memenuhi 1 <= I <= 24, I merupakan integer.
Batas bawah dari array, pada beberapa aplikasi, tidak selalu diambil 1. Kadang-kadang diambil batas bawah nol, bahkan juga negatif. Banyaknya elemen sebuah array disebut rentang atau range. Jadi array A(L:U) mempunyai range sebesar U-L+1. Secara
khusus bila L=l dan U=N, maka range dari array A(l:N) adalah N-I+1 = N.

- ARRAY DIMENSI BANYAK

Sebuah array dimensi banyak atau multi-dimensional array didefinisikan sebagai sebuah
array yang elemennya berupa array pula. Misal array B mempunyai M elemen berupa array pula, yang terdiri dari N elemen.

Untuk itu diperlukan dua buah subscript. Yang pertama digunakan untuk menyatakan
posisi baris, sedangkan yang kedua untuk posisi kolom. Secara umum array dimensi dua
B, dengan elemen bertipe data T, subscript baris dari l sampai M, subscript kolom dari l sampai N, ditulis sebagai B(1:M, 1:N) = (B(I,J)), I = 1, 2, ...,M dan J = 1, 2,...,N dengan setiap elemen B(I,J) bertipe data T. Array B tersebut dikatakan berukuran atau berorder M x N. Di sini banyak elemen array adalah M*N.

Contoh dari array dimensi dua sangat banyak kita jumpai. Misalnya nilai ujian 500
mahasiswa Gunadarma tingkat 3, untuk 8 mata kuliah dapat kita sajikan sebagai array
dimensi dua yang berorder 500 x 8. Elemen B(I,J) menyatakan nilai mahasiswa ke-I untuk mata kuliah ke-J. Seperti halnya pada array dimensi satu, pada array dimensi dua batas bawah untuk subscript I maupun J dapat diambil secara umum. Misalnya, batas bawah subscript baris adalah L1 subscript kolom adalah L2 sedangkan batas atas subscript baris adalah U1 dan untuk kolom adalah U2, maka array dimensi dua tersebut dapat dinotasikan sebagai :

B(L1:U1, L2:U2) = (B(I,J)), L1 <= 1 <= U1, L2 <=J <= U2

dengan setiap elemen B(I,J) bertipe data T. Banyaknya elemen pada setiap baris adalah U2 – L2 + 1 dan pada setiap kolom adalah U1–L1+l, sehingga banyaknya elemen pada array B semua ada = (U2-L2 +1) * (U1-L1 +1).

Yang dimaksud dengan cross-section suatu array berdimensi dua adalah pengambilan
salah satu subscript, misalnya subscript baris untuk tetap atau konstan, sementara subscript yang satunya lagi kita ubah-ubah sepanjang rangenya. Notasi yang umum digunakan

Dengan mudah dapat dimengerti bahwa B(11,*) menunjukkan semua elemen pada baris
ke-11. Transpose dari suatu array dimensi dua adalah penulisan baris menjadi kolom (kolom menjadi baris) dari suatu array. Jadi transpose dari array berorder M x N adalah array berorder N x M. Transpose dari array B dinotasikan sebagai BT. Berdasarkan definisi, maka jelas B(I,J) =BT(J,I). Contohnya B(3,5) = BT(5,3).

Pengertian di atas dapat kita perluas untuk array dimensi tiga, dimensi empat, sampai
dimensi N. Array dimensi N kita tulis sebagai :

A(L1:U1, L2:U2, …, LN: UN) = (A(I1, I2, …, IN))

dengan Lk <= Ik <= Uk, untuk setiap k = 1, 2, …, N.

Banyaknya elemen dari array A tersebut adalah :
PI(Uk - Lk + 1) = (U1-L1+1) * (U2 – L2+1) … * (UN -LN + 1)

Contoh array dimensi tiga adalah penyajian data mengenai banyaknya mahasiswa
dari-20 perguruan tinggi di Jakarta, berdasarkan tingkat (tingkat 1, 2 sampai dengan 5), dan jenis kelamin (pria atau wanita). Misalnya array tersebut dinamakan MHS. Ambil sebagai subscript pertama, tingkat : I = 1, 2,...,5; subscript kedua, jenis kelamin (pria = 1, wanita = 2): J = 1,2, dan subscript ke-3, Perguruan Tinggi adalah K = 1,2,...,20. Jadi MHS(4,2,17)

Pengertian cross-section pada array dimensi banyak, adalah sama seperti pada array
dimensi dua. Misalnya MHS(4,*,17) menunjukkan jumlah mahasiswa tingkat 4 dari
perguruan tinggi 17 (masing-masing untuk pria serta wanita). MHS(*,*,3) menun-jukkan
jumlah mahasiswa untuk masing-masing tingkat, pria serta wanita, dari perguruan tinggi 3.


- DEKLARASI ARRAY DALAM BAHASA PEMROGRAMAN

Misalkan kita hendak mendeklarasikan array TEMP yang merupakan array dimensi satu dengan nilai subscript 1 sampai 24, dan masing-masing elemen bertipe data integer (nilainya antara 0 hingga 99 derajat).
Dalam Bahasa COBOL dapat ditulis :
01 TABEL-TEMP
02 TEMP OCCURS 24 TIMES PIC 99.
Dalam bahasa Pascal :
var temp: array l..24)of integer
Dalam Bahasa BASIC, kita dapat mendefinisikan array TEMP tersebut dengan
statement :
DIM TEMP(24)
Tiga hal harus dikemukakan dalam mendeklarasikan suatu array, yakni :
1. nama array
2. range dari subscript
3. tipe data dari elemen array
Bahasa Pascal memperkenankan batas bawah subscript yang bukan =1, contohnya
adalah :
var grafik : array [-100 ..100] of integer
Dalam COBOL subscript harus dimulai dari 1.
Untuk menyatakan elemen ke-I dari array, COBOL dan BASIC menggunakan kurung
biasa, yakni TEMP(I), sedangkan Pascal menggunakan kurung siku, yakni temp[i].
Untuk mendeklarasikan sebuah array nilai dari 500 mahasiswa untuk 8 mata kuliah,

dalam COBOL ditulis

01 TABEL-NILAI
02 MHS OCCURS 500 TIMES
03 NILAI OCCURS 8 TIMES
PIC 99V9.

Dalam Pascal ditulis :
var nilai : Array[1..500,1..8] of real
dan dalam BASIC dapat ditulis
DIM NILAI(500,8)

Dalam COBOL maksimum dimensi yang dapat diterima adalah 3 (three dimensional),
contohnya :
01 MHS-TABEL
02 TINGKAT OCCURS 5 TIMES
03 SEX OCCURS 2 TIMES
04 MHS OCCURS 20 TIMES PIC 9(5).

dan dalam Pascal :
var mhs : Array[1..5, 1..2, 1..20] of integer

Dalam bahasa pemrograman seperti FORTRAN dan COBOL, alokasi untuk array
dalam storage memerlukan waktu dalam proses kompilasi, karenanya batas bawah dan
batas atas harus dikemukakan ketika mendefinisikan array.

COBOL dan Pascal (juga bahasa lain yang memungkinkan pendeklarasian array)
mempunyai fasilitas untuk melakukan manipulasi antarelemen array. Operasi yang sesuai
dengan tipe data array tersebut dapat dikerjakan dengan mudah,

contohnya dalam COBOL
COMPUTE TOTAL_UPAH(I) = UPAH_PER_JAM(I) * JUMLAH-JAM(l)

Terlihat bahwa ketiga variabel di atas adalah array.
Beberapa bahasa pemrograman memperkenankan operasi array. Sebagai contoh, A
adalah array (bertipe real) yang dideklarasi dalam PL/1, maka A=A+2 adalah operasi
untuk menambah setiap elemen dari A dengan bilangan 2.
Juga dikenal operasi A = A * B. Operasi ini menghasilkan array A baru yang
elemennya merupakan hasil kali elemen array A (lama) dengan elemen array B yang
posisinya bersesuaian. Order array A dan B harus sama.

Perhatikan bahwa perkalian array ini bukan perkalian matriks yang telah kita kenal.
Dalam PL/1, operasi dapat pula dilakukan terhadap cross-section.

Sebagai contoh adalah operasi yang menyebabkan NILAI seluruh baris 20 menjadi nol, berikut ini :
NILAI(20,*)= 0
Operasi VEKTOR(*)= ARRAY1(I,*) *ARRAY(*,J) akan memperkalikan elemen
baris ke-I dari ARRAY1 dengan elemen kolom ke-j dari ARRAY2.

Operasi di atas mempunyai efek yang sama seperti loop dalam Bahasa BASIC :
FOR K = 1 TO N
VEKTOR(J)


- PEMETAAN ARRAY DIMENSI SATU KE STORAGE

Seperti halnya struktur data yang lain, ada beberapa cara untuk menyajikan array di dalam memori. Skema penyajian dapat dievaluasi berdasarkan 4 karakteristik, yakni :
1. kesederhanaan dari akses elemen
2. mudah untuk ditelusuri
3. efisiensi dari utilitasi storage
4. mudah dikembangkan

Umumnya tidaklah mungkin untuk mengoptimalkan keempat faktor tersebut
sekaligus. Pandang array satu dimensi NOPEG dengan batas bawah subscript 1, dan batas
atas subscript = N. Salah satu cara untuk menyimpan array ini adalah sedemikian sehingga urutan fisik dari elemen sama dengan urutan logik dari elemen. Storage untuk elemen NOPEG(I+1) adalah berdampingan dengan storage untuk elemen NOPEG(I), untuk setiap I = 1, 2, 3,..., N-1. Untuk menghitung alamat (address) awal dari elemen NOPEG(I), diperlukan untuk mengetahui 2 hal yakni :
1. address awal dari ruang storage yang dialokasikan bagi array tersebut.
2. ukuran dari masing-masing elemen array.

Address awal dari array, kita nyatakan dengan B, disebut juga base-location. Misalkan
bahwa masing-masing elemen dari array menduduki S byte.

Maka, address awal dari elemen ke-I adalah :
B + (I-1) * S

Sekarang kita perluas persamaan di atas untuk mendapat address dari elemen ke-I dari
array yang mempunyai batas bawah subscript tidak sama dengan 1. Perhatikan array
Z(4:10), maka address awal dari Z(6) adalah :

B + (64) * S

Untuk array Z2 (-2:2) misalnya, address awal dari Z2(l) adalah :
B + (I -(-2)) * S

Maka secara umum, untuk array :
ARRAY(L:U),

elemen ARRAY(I) mempunyai address awal
B + (U-L) * S

- PEMETAAN KE STORAGE TERHADAP ARRAY DIMENSI BANYAK

Karena memori komputer adalah linear, maka array dimensi banyak harus dilinearkan
apabila akan dipetakan ke dalam storage. Salah satu alternatif untuk pelinearan tersebut adalah menyimpan pertama kali baris pertama dari array, kemudian baris ke-2, baris ke-3 dan seterusnya. Ini disebut row major order.

Misalkan B adalah base-location dari array RATE tersebut, dan masing-masing elemen
dari array berukuran S. Address awal dari elemen RATE(I,J) adalah :

B + (I-1) * 6 * S + (J-1) * S

karena ada I-1 baris, masing-masing dengan panjang 6 * S, sebelum baris elemen
RATE(I,J) terletak, dan terdapat J- 1 elemen, masing-masing dengan panjang S sebelum
elemen RATE(I,J) pada baris ke-I. Jadi, pada contoh di atas RATE(2,4) mempunyai
address awal :

B+ (2-1) * 6 * S + (4-1) * S = B + 9 * S

Secara umum elemen ARRAY(I,J) dari array yang didefinisikan sebagai
ARRAY(L1:U1, L2 : U2) mempunyai address awal :

B + (I-L1) * (U2 -L2+ 1) * S + (J-L2) * S

Terdapat 2 baris (I-L1, 0 – (-2)) sebelum baris nol, yang masing-masing panjangnya 3*
S(U2-L2+1 = 6-4+1) dan terdapat 2 elemen (J-L2 = 6-4) pada baris ke nol sebelum elemen Z (0,6). Jadi address awal dari Z(0,6) adalah :

B + 2 * 3 * S + 2 * S = B + 8 * S

Alternatif lain untuk melinearkan array dimensi dua adalah dengan menyimpan
elemen dalam column major order, yakni pertama kali menyimpan kolom pertama, lalu
kolom kedua, kolom ketiga dan seterusnya.

Dengan mudah dapat diterangkan bahwa pada array RATE di atas, elemen RATE(I,J)
mempunyai address awal B + (J - 1) * 4 * S + (I - 1) * S, sehingga RATE(2,4) akan
mempunyai address awal B + (4-1) * 4 * S + (2-1) * S = B + 13 * S. Jadi kita harus
waspada andaikata kita mempunyai array yang ditulis dalam rutin FORTRAN, kemudian
akan kita tulis dalam bahasa lain (COBOL, PL/1 atau Pascal). Secara umum, elemen
ARRAY(I,J) dari array yang didefinisikan sebagai ARRAY(L1:U1,L2 :U2), menggunakan address awal :

B + (J-L2) * (U1-L1 +1) * S + (I-L1) * S

Misalkan array A berorder 50 x 225. Hendak dihitung jumlah / total elemennya. Kalau
dipergunakan column-major storage, dapat kita buat, dalam COBOL.

COMPUTE TOTAL = 0.
PERFORM SUM-UP VARYING J
FROM 1 BY 1 UNTIL J > 225
AFTER 1 FROM 1 BY 1 UNTIL I > 50.

dalam hal ini
SUM-UP.
TOTAL = TOTAL + A(I,J).

Dalam Pascal dapat kita tulis :
Total := 0;
for j = 1 to 225 do
for i = 1 to 50 do
total := total + a[I,j];

Kalau dipergunakan row-major storage, kita dapat tulis dalam COBOL sebagai berikut :
COMPUTE TOTAL = 0.
PERFORM SUM-UP VARYING 1
FROM 1 BY 1 UNTIL I > 50
AFTER J FROM 1 BY 1 UNTIL J > 225

dalam hal ini
SUM-UP.
TOTAL = TOTAL + A(I,J).

dan dalam Pascal dapat ditulis
total:=0;
for i := 1 to 50 do
for j := 1 to 225 do
total := total + a[i,j];


- TRINGULAR ARRAY (ARRAY SEGITIGA)

Akan kita tinjau beberapa aspek pelinearan suatu array yang khusus, yakni tringular
array. Tringular array dapat merupakan upper tringular (seluruh elemen di bawah
diagonal utama = 0) ataupun lower tringular (seluruh elemen di atas diagonal utama =0).

Dalam array lower triangular dengan N baris, jumlah maksimum elemen <> 0 pada
baris ke-I adalah 1, karenanya total elemen <> 0, tidak lebih dari :

N
Σ I = N(N+1)/2
I = 1

Gambar 2.10 menunjukkan triangular array berorder 6 x 6.
X X X X X X X 0 0 0 0 0
0 X X X X X X X 0 0 0 0
0 0 X X X X X X X 0 0 0
0 0 0 X X X X X X X 0 0
0 0 0 0 X X X X X X X 0
0 0 0 0 0 X X X X X X X
(a) (b)

Gambar 2.10 (a) Upper triangular array (b) Lower triangular array
Rumus ini berlaku pula untuk array upper tringular dengan N baris. Kalau N besar,
alangkah baiknya kalau elemen nol tidak usah kita simpan dalam memori. Suatu
pendekatan terhadap problema ini adalah dengan pelinearan array, dan dengan hanya
menyimpan bagian array yang tidak nol. Misalkan kita menyimpan array upper tringular T secara baris dalam array satu dimensi S, dengan batas subscript I sampai N(N+I)/2. Elemen T(1,1) disimpan sebagai S(1), elemen T(1,2) sebagai S(2) dan seterusnya, sehingga elemen T(1,N) disimpan sebagai S(N). Maka elemen T(2,2) disimpan sebagai S(N+1) (karena T(2,1) = 0).

Terakhir sekali, elemen T(N,N) akan disimpan sebagai S(N(N+1)/2). Kadang-kadang suatu program menggunakan lebih dari satu array tringular. Untuk itu kita dapat menyimpan 2 array sekaligus. Misalnya array A upper triangular berorder
N x N dan array B lower triangular berorder (N-1) x (N-1). Mereka dapat kita simpan sebagai array C berorder N x N. Di sini C(l,J) = A(l,J) untuk I <= J dan C(I+1,J) = B(I,J) untuk I >= J.

Sekarang apabila array A upper tringular berorder N x N sedangkan array B lower
tringular, juga berorder N x N, maka array C yang mengandung keduanya harus berorder
N x (N+1). Di sini elemen A(I,J) disimpan sebagai C(I,J+1) untuk I <= J, dan B(I,J)
disimpan sebagai C(I,J) untuk I >= J.

Perhatikan contoh berikut array A berorder (3 x 3) merupakan upper tringular.

1 2 3
0 4 5
0 0 6

Array B berorder (2 x 2) merupakan lower tringular,

7 0
8 9


maka mereka disimpan bersama dalam array C sebagai

1 2 3
7 4 5
8 9 6

Contoh berikut,

1 2 3 7 0 0
A = 0 4 5 B = 8 9 0
0 0 6 11 12 13

dapat disimpan sebagai array C berorder (3 x 4)

7 1 2 3
8 9 4 5
11 12 13 6

Misalkan sekarang ada 2 array, sama-sama upper tringular, yakni array A1 dan A2.
Kita dapat menyimpan mereka bersama-sama dengan melakukan transpose terhadap salah
satu array tersebut, misalnya A2 menjadi A2T. A2T adalah array lower tringular. Array C berorder N x (N+1) akan menyimpan elemen A1(I,J) sebagai C(I,J+1) untuk I <= J, dan elemen A2(I,J) akan disimpan sebagai C(J,I) untuk I >= J.

Sebagai contoh adalah array :

1 2 3 7 8 9
A1 = 0 4 5 A2 = 0 11 12
0 0 6 0 0 13

7 0 0
maka A2T = 8 11 0
9 12 13

dan mereka tersimpan sebagai :

7 1 2 3
C = 8 11 4 5
9 12 13 6


- DEFINISI RECORD

Sebuah record merupakan koleksi satuan data yang heterogen, yakni terdiri dari berbagai
type. Satuan data tersebut sering disebut sebagai field dari record. Field dipanggil dengan
menggunakan namanya masing-masing. Suatu field dapat terdiri atas beberapa subfield.
Sebagai Contoh, data personalia dari seorang pegawai suatu perusahaan di Amerika
Serikat, merupakan sebuah record yang dapat terdiri dari berbagai field, dan subfield
seperti berikut ini :

1 NOMOR-JAMINAN-SOSIAL
2 NAMA, yang terdiri atas :
NAMA-BELAKANG
NAMA-DEPAN
NAMA-TENGAH
3 ALAMAT, terdiri atas :
JALAN
NOMOR RUMAH
NAMA-JALAN
KOTA
NEGARA-BAGIAN
KODE-POS
4 MENIKAH

Pada record tersebut di atas, satuan data seperti NAMA BELAKANG ataupun KOTA
merupakan tipe data string, sedangkan data lain seperti GAJI POKOK, TUNJANGAN
JABATAN dan berbagai data yang akan diolah secara matematis akan disimpan dengan
tipe data numerik, bisa integer maupun real. Data MENIKAH bisa digunakan tipe data
boolean atau logikal.

Seperti telah kita paparkan terdahulu, array berbeda dengan record, yakni array
bersifat homogen (terdiri dari tipe data yang sama), dan komponen array tidak memiliki
nama sendiri, dan hanya diberi identifikasi oleh posisi mereka di dalam array. Penggunaan
keduanya di dalam program juga berbeda, jika penggunaan array pada umumnya akan
disimpan di memori utama komputer (bersifat sementara), sedangkan record biasanya
digunakan dalam filing yang akan disimpan di memori sekunder komputer, seperti hard
disk, disket, dan lainnya.

Sebuah record memberi informasi tentang berbagai kondisi dari obyek pada
permasalahan yang nyata sehari-hari. Setiap field memberi uraian tentang satu atribut dari
obyeknya. Sebuah record biasanya diberi identifikasi oleh key-nya. Key atau kunci adalah
salah satu atau lebih field yang dipilih untuk tujuan penyampaian informasi yang terjadi di
dalam record yang bersangkutan.

Koleksi dari record yang sama struktur fieldnya disebut suatu file atau berkas. Jadi,
koleksi dari record semua pegawai perusahaan membentuk sebuah file personalia. Pada
umumnya record disimpan membentuk file, dalam urutan sesuai dengan nilai dari key
masing-masing. Di dalam suatu file PERSONALIA, field NOMOR JAMINAN SOSIAL
dari seorang pegawai dapat digunakan sebagai key. Di dalam bahasa pemrograman tingkat
tinggi, record dapat dinyatakan sebagai struktur data (COBOL dan PL/1) dapat diadakan
spesifikasi tentang nama record, field dan subfield yang bersangkutan.

Record tersebut juga diberi nomor seperti diperlihatkan di dalam contoh di bawah ini.
Deklarasi berikut ini dapat digunakan untuk menuliskan record dari file PERSONALIA di
atas.
01 PEGAWAI
02 NOMOR-JAMINAN-SOSIAL
02 NAMA
03 NAMA-BELAKANG
03 NAMA-DEPAN
03 NAMA-TENGAH
02 ALAMAT
03 JALAN
04 NOMOR RUMAH
04 NAMA-JALAN
03 KOTA
03 NEGARA-BAGIAN
03 KODE-POS
02 MENIKAH