Koleksi
Bab ini mengintroduksi sejumlah kelas koleksi
di dalam pustaka .NET, dengan ide bahwa koleksi objek dapat membantu membangun
konsep-konsep yang nantinya dapat diterapkan pada database. Anda akan belajar
bagaimana menciptakan dan menggunakan ArrayList,
List, dan Dictionary. Bab ini
akan menyajikan contoh-contoh bagaimana menggunakan teknologi LINQ (Language Integrated Query) untuk
melakukan pencarian terhadap objek.
3.1 ArrayList
Dengan istilah yang paling umum, koleksi
adalah sekelompok nilai yang beruntun atau tak-beruntun. Pada sebuah koleksi
beruntun yang dikenal dengan list,
nilai-nilai ditempatkan pada posisi-posisi yang relatif satu sama lain. Sebagai
contoh, sebuah list yang memuat cuplik-cuplik suhu yang diambil setiap jam
selama sehari. Array dapat dipandang sebagai list. Jenis lain dari koleksi
adalah set, yang tidak memiliki
runtun tertentu. Jenis lain dari koleksi adalah Dictionary atau map,
yang melekatkan setiap kunci dengan nilai tertentu. Jika Anda ingin mencari
transkript akademik dari seorang siswa, misalnya, Anda dapat menggunakan ID
siswa sebagai kunci. Nilai yang
berkaitan dengan tiap kunci di dalam kamus, pada kasus ini, adalah transkript
siswa.
Pustaka .NET memiliki sejumlah kelas yang
mengimplementasikan beberapa jenis koleksi. Pada bab ini, Anda akan mempelajari
ArrayList, List, dan Dictionary.
Gambar 3.1 Relasi-relasi pada ArrayList
Kelas ArrayList
Koleksi .NET yang paling fundamental adalah
kelas ArrayList, yang merupakan
koleksi tipe-list yang dapat mengembang yang memuat referensi-referensi ke
objek-objek. ArrayList merupakan
bagian dari namespace System.Collections.
Seperti array, ArrayList juga dapat
menggunakan subskript untuk secara acak mengakses elemen-elemennya. ArrayList lebih tangguh dan fleksibel
dari array biasa karena aspek-aspek berikut:
- ArrayList akan mengembang atau membesar ketika item-item baru disisipkan, sedangkan array tidak bisa melakukannya.
- ArrayList memuat metode-metode untuk melakukan pencarian, penyisipan, dan penghapusan item, sedangkan array tidak bisa melakukannya.
Anda dapat menyisipna sejumlah objek berbeda tipe ke dalam objek ArrayList yang sama.
Gambar 3.1 menunjukkan beberapa relasi antara
ArrrayList dengan item-item yang
dimuatnya. Tabel 3.1 mencantumkan sejumlah properti dan metode dari ArrayList.
Tabel 3.1 Properti-properti dan metode-metode pada
kelas ArrayList
Properti Atau Metode
|
Penjelasan
|
Add(elemen
As Object)
Clear(
)
Contains(
elemen As Object ) As Boolean
Count(
) As Integer
Insert(indeks
As Integer, elemen as Object)
Item(
indeks As Integer ) As Object
Remove(
elemen As Object )
RemoveAt(
indeks As Integer )
|
Menambahkan
sebuah item di akhir list
Menghapus
semua item dari list
Menghasilkan
True jika list memuat item yang
ditentukan
Menghasilkan
banyak item di dalam list
Menyisipkan
sebuah item ke dalam list pada posisi indeks tertentu.
Menghasilkan
sebuah referensi yagn menunjuk ke item list pada posisi indeks tertentu.
Menghapus
kemunculan pertama dari item tertentu dari list.
Menghapus
item pada posisi indeks tertentu.
|
Menciptakan Sebuah ArrayList
Anda menggunakan operator New untuk
menciptakan sebuah objek dari kelas ArrayList. Sebagai contoh:
Dim
konsumen As New ArrayList
Anda dapat pula melewatkan sebuah array,
sebuah ArrayList, atau sembarang
objek yang mengimplementasikan antarmuka ICollection
kepada konstruktor ArrayList. Pada
kode berikut, misalnya, ArrayList
menerima sebuah salinan dari array skor:
Dim
skor() As Integer = {80, 66, 75}
Dim skorList
As New ArrayList(skor)
Menambah dan Menyisipkan Item
Salah satu cara dalam menambah item ke sebuah
ArrayList adalah dengan memanggil
metode Add. Berikut adalah
contohnya:
konsumen.Add(“Bakri”)
Anda dapat pula menggunakan metode Insert untuk menempatkan sebuah item ke
dalam list pada posisi tertentu:
skorList.Insert(1,”Roro
Kusuma”)
Tidak ada batasan pada penyisipan item
duplikat, jadi jika persyaratan aplikasi Anda tidak membolehkan adanya item
duplikat, Anda perlu memeriksanya sendiri.
Menghapus Item
Metode RemoveAt
menghapus sebuah item ArrayList.
Anda dapat melewatkanya kepadanya posisi indeks dari item yang ingin dihapus.
Statemen berikut menghapus sebuah item pada posisi indeks 2:
konsumen.RemoveAt(2)
Metode Remove
menghapus item pertama yang cocok dengan item yang dilewatkan sebagai parameter
masukan. Statemen berikut menghapus “Bakri” dari ArrayList konsumen:
konsumen.Remove(“Bakri”)
Mencari Item
Metode Contains
menghasilkan sebuah nilai Boolean yang mengindikasikan apakah nilai tertentu
ada di dalam sebuah ArrayList. Pada
contoh berikut, variabel ditemukan akan bernilai True jika nilai 66 ada di dalam ArrayList dengan nama skorList:
Dim
ditemukan As Boolean = skorList.Contains(66)
Metode IndexOf
menghasilkan sebuah integer yang mengidentifikasi posisi indeks dari sebuah
item. Jika item tidak ditemukan, nilai yang dihasilkan adalah -1. Kode berikut
memanggil IndexOf dan menampilkan
sebuah pesan jika nama konsumen tidak ditemukan:
Dim
indeks As Integer = konsumen.IndexOf(“Bakri”)
If
indeks = -1 Then
labelStatus.Text = “Konsumen tidak
ditemukan”
End If
Membaca dan Mengganti Item
Properti Item
menghasilkan sebuah referensi yang menunjuk ke suatu elemen ArrayList. Anda melewatkan kepada
properti Item sebuah indeks integer
antara 0 dan ArrayList.Count-1.
Sebagai contoh, kode berikut membaca nilai yang disimpan pada posisi indeks 2
pada ArrayList dengan nama konsumen:
Dim
nama As String = CStr(konsumen.Item(2))
Karena ekspresi konsumen.Item(2) menghasilkan sebuah tipe data Object, Anda perlu mengkonversinya menjadi tipe String sebelum menugaskannya kepada
variabel nama.
Item disebut pula sebagai properti default, jadi
statemen berikut secara implisit membaca elemen pada posisi indeks 2:
Dim
nama As String = CStr(konsumen(2))
Anda dapat menggunakan properti Item untuk mengganti sebuah item di
dalam ArrayList. Kode berikut
menunjukkan dua cara dalam mengganti item pada indeks 2 dengan “John”:
konsumen.Item(2)
= “John”
konsumen(2)
= “John”
Eksepsi IndexOutOfRangeException
Sebuah eksepsi IndexOutOfRangeException dilemparkan ketika Anda melewatkan sebuah
indeks kepada properti Item yang
tidak cocok dengan indeks dari setiap item di dalam sebuah ArrayList. Kode berikut menunjukkan bagaimana menangani eksepsi
ini:
Try
Dim indeks As Integer = CInt(teksIndeks.Text)
Dim kons As String = CStr(konsumen.Item(indeks))
Catch
ex As IndexOutOfRangeException
MessageBox.Show(ex.Message)
End
Try
Aturan yang sama berlaku ketika Anda
memanggil metode RemoveAt, yang juga
harus menerima indeks yang valid.
Properti Count
Properti Count
mengindikasikan banyak item yang disimpan di dalam sebuah ArrayList. Kode berikut menggunakan properti Count untuk menampilkan ukuran dari list konsumen:
labelInfo.Text
= “Ukuran koleksi adalah “ & konsumen.Count
Loop
Cara mudah untuk menjelajak ArrayList adalah dengan menggunakan
statemen For Each. Selama tiap iterasi, variabel yang dideklarasikan di dalam
loop merepresentasikan nilai item terkini. Kode berikut menjelajah skorList dan
menambahkan tiap skor pada sebuah kotak list:
For
Each skor As Integer In skorList
kotakList.Items.Add(skor)
Next
Sama halnya, kode berikut menjelajah ArrayList dengan nama konsumen dan menambahkan tiap elemennya
pada sebuah kotak list:
For
Each kons As String In konsumen
kotakList.Items.Add(kons)
Next
Pada Tutorial 3.1, Anda akan menciptakan
sebuah aplikasi yang membangun suatu ArrayList
yang memuat sejumlah skor ujian.
Tutorial 3.1: ArrayList yang Memuat Sejumlah Skor Ujian
Pada tutorial
ini, Anda akan menciptakan sebuah aplikasi yang memiliki sebuah kelas Siswa yang memuat sebuah ArrayList yang terdiri-dari sejumlah
skor ujian. Ketika tiap skor ujian dimasukkan oleh user, ia akan ditambahkan
pada list. Sebuah properti ReadOnly
di dalam kelas akan menghitung rerata ujian. Kelas juga memuat sebuah variabel
shared yang memuat nama sekolah, dengan sebuah properti shared terkait.
Gambar 3.2
menunjukkan keluaran aplikasi setelah user memasukkan ID siswa dan nama, dan
telah mengklik tombol Simpan. Kemudian, ketika user memasukkan sejumlah skor
ujian dan mngklik tombol Lihat,
contoh keluaran ditampilkan pada Gambar 3.3. User dapat melanjutkan memasukkan
skor ujian lainnya dan mengklik tombol Lihat
sebanyak yang diinginkan.
Gambar 3.2 Setelah mengklik tombol Simpan
Gambar 3.3 Setelah user menambahkan dua skor dan
mengklik tombol Lihat
Langkah-Langkah Tutorial
Langkah 1: Buka projek Koleksi
Skor Ujian. Kontrol-kontrol diberinama berikut:
·
Kontrol-kontrol TextBox: teksNomorID, teksNamaBelakang, dan teksNilai
·
Kontrol-kontrol Label: labelRerataUjian, labelSiswa, dan labelSekolah
·
Kontrol-kontrol Button: tombolTambahkan, tombolSimpan, dan tombolLihat.
Langkah 2: Buka kelas Siswa
pada editor kode dan lihat kode berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Public Class Siswa
Public Property NomorId As
String
Public Property NamaBelakang
As String
Public Shared Property
NamaSekolah As String
Private mSkorUjian As New
ArrayList
Public ReadOnly Property
RerataUjian() As Double
Get
Dim jumUjian As
Double = 0.0
For Each nilai As
Double In mSkorUjian
jumUjian +=
nilai
Next
If mSkorUjian.Count
> 0 Then
Return jumUjian
/ mSkorUjian.Count
Else
Return 0.0
End If
End Get
End Property
|
ArrayList dideklarasikan pada baris 5. Baris 13 memeriksa nilai
dari mSkorUjian.Count, untuk
menghindari pembagian dengan nol ketika tidak ada skor ujian yang ditambahkan
pada koleksi. Baris 14 menghitung dan menghasilkan rerata ujian.
Metode-metode
yang memuat sebuah konstruktur, sebuah metode untuk menambahkan nilai ujian
pada koleksi, dan sebuah metode ToString:
Public Sub New(ByVal pNomorId As String,
Optional ByVal pNamaBelakang As String = "")
NomorId = pNomorId
NamaBelakang = pNamaBelakang
End
Sub
Public Sub TambahkanNilaiUjian(ByVal nilai As Double)
mSkorUjian.Add(nilai)
End
Sub
Public Overrides Function ToString() As String
Return NomorId & ", " & NamaBelakang
End
Function
End Class
Langkah 3: Buka jendela Code
untuk Form1.vb dan periksa kode
berikut:
Public Class Form1
Private objSiswa As Siswa
Event handler
Form1_Load menetapkan nilai dari
properti shared NamaSekolah di dalam
kelas Siswa:
Private Sub Form1_Load(…) Handles MyBase.Load
Siswa.NamaSekolah = "Sekolah
Tarabunga"
End Sub
Langkah 4: Lihat handler Click
untuk tombol Simpan:
Private Sub tombolSimpan_Click(…) Handles
tombolSimpan.Click
objSiswa = New Siswa(teksNomorID.Text,
teksNamaBelakang.Text)
labelSiswa.Text = "(informasi siswa
telah disimpan)"
tombolTambahkan.Enabled = True
End Sub
Metode ini
menciptakan sebuah objek Siswa yang
baru dari dua kotak teks. Perhatikan bagaimana tombol Tambahkan diaktifkan hanya ketika user mengklik tombol Simpan. Ini perlu untuk mencegah
program mencoba menjumlahkan skor sebelum sebuah objek Siswa diciptakan. Tombol Tambahkan
dipakai user untuk menjumlahkan skor-skor ujian pada koleksi skor dari siswa terkait.
Langkah 5: Lihat handler Click
untuk tombol Lihat, yang menampilkan
ID siswa dan nama belakangnya, nama sekolah, dan rerata ujian siswa:
Private Sub tombolLihat_Click(…) Handles
tombolLihat.Click
labelSiswa.Text = objSiswa.ToString
labelSekolah.Text = Siswa.NamaSekolah
labelRerataUjian.Text = objSiswa.RerataUjian.ToString("n")
End
Sub
Langkah 6: Event handler Click
untuk tombol Tambahkan mengambil nilai ujian dari kotak teks teksNilai dan memanggil metode Siswa.TambahkanNilaiUjian. Metode ini
menambahkan nilai pada koleksi nilai dari mahasiswa:
Private Sub tombolTambahkan_Click(…) Handles
tombolTambahkan.Click
Dim nilaiUjian As Double
If Double.TryParse(teksNilai.Text, nilaiUjian)
Then
objSiswa.TambahkanNilaiUjian(nilaiUjian)
Else
MessageBox.Show("Nilai ujian harus
berupa angka", "Error")
End
If
End Sub
Langkah 7: Simpan projek dan jalankan aplikasi.
3.2 ArrayList yang Memuat Objek-Objek
Anda telah melihat bagaimana menciptakan ArrayList yang memuat tipe-tipe
standar, seperti String dan Double. Anda juga dapat menciptakan
list yang memuat objek-objek dari kelas Anda sendiri. Dimisalkan bahwa Anda
ingin menciptakan sebuah list yang memuat objek-objek Siswa. Pekerjaan-pekerjaan berikut dilakukan pada list:
·
Menjelajah list dan menampilkan tiap siswa
·
Melakukan pencarian siswa
·
Mengurutkan list
·
Menghapus sebuah siswa dari list
Anda harus menciptakan sebuah objek baru dari
kelas Siswa setiap kali Anda
menyisipkan sebuah objek baru, untuk menghindari penciptaan sebuah ArrayList dimana di dalamnya semua item
mereferensi objek yang sama. Selain itu, kelas Siswa perlu mengimplementasikan
metode Equals dan CompareTo.
Referensi dan Salinan
Ketika sebuah item di dalam suatu ArrayList adalah sebuah tipe nilai
seperti Integer atau Single, metode Item menghasilkan salinan item. Sebagai contoh, kode berikut
menyisipkan sebuah integer ke dalam suatu ArrayList
dengan nama angka:
Dim
angka As New ArrayList
angka.Add(10)
Selanjutnya, kode berikut membaca integer
yang disimpan pada indeks 0 dan memodifikasi nilainya:
Dim
intNil As Integer = CType(angka.Item(0), Integer)
intNil
= 99
Tetapi intNil
hanyalah salinan dari item pada koleksi, jadi item yang disimpan di dalam ArrayList pada indeks 0 sama dengan
nilai awalnya, 10.
Tetapi ketika sebuah item di dalam ArrayList adalah tipe referensi, metode
Item menghasilkan referensi yang
menunjuk ke objek. Referensi dapat dipakai untuk memodifikasi objek di dalam
list. Untuk mengilustrasikannya, Anda dapat menciptakan sebuah ArrayList dengan nama siswa dan menyisipkan sebuah objek Siswa:
Dim
siswa As New ArrayList
siswa.Add(New
Siswa(“Kristof”))
Selanjutnya, Anda menggunakan metode Item untuk mendapatkan sebuah referensi
yang menunjuk ke siswa yang sama:
Dim
siswaRef as Student = CType(siswa.Item(0), Siswa)
Selanjutnya, Anda menugaskan sebuah nama
belakang baru kepada referensi siswa:
siswaRef.NamaBelakang
= “Bening”
Dengan melakukannya, Anda juga telah
memodifikasi nama dari objek Siswa
yang ada di dalam ArrayList. Ini
karena metode Item menghasilkan
referensi ke objek di dalam ArrayList.
Error yang Sering Terjadi: Beberapa
Referensi ke Objek yang Sama
Dengan memahami bagaimana referensi bekerja,
Anda dapat terhindar dari error yang sering terjadi ketika bekerja dengan
koleksi, yaitu error yang menyimpan beberapa referensi yang menunjuk ke objek
yang sama. Kode berikut (ditempatkan di dalam handler Click untuk sebuah tombol dengan nama Tambahkan) menunjukkan cara tepat untuk menyisipkan sebuah objek ke
dalam ArrayList:
1
2
3
4
5
6
7
|
Private
SemuaSiswa As New ArrayList
Private
Sub tombolTambahkan_Click() Handles tombolTambahkan.Click
Dim objSiswa As New Siswa(teksNomorID.Text,
teksNamaBelakang.Text, CDbl(teksRerataUjian.Text))
SemuaSiswa.Add(objSiswa)
End Sub
|
Baris 4 menciptakan sebuah objek Siswa yang baru, dengan menggunakan
nilai dari tiap kotak teks. Baris 6 menambahkan siswa tersebut ke dalam ArrayList. Selanjutnya, lihat kode yang
sama yang memuat error yang sering dilakukan:
1
2
3
4
5
6
7
8
9
|
Private SemuaSiswa As New
ArrayList
Private objSiswa As New Siswa
Private Sub
tombolTambahkan_Click() Handles tombolTambahkan.Click
objSiswa.NomorID = teksNomorID.Text
objSiswa.NamaBelakang = teksNamaBelakang.Text
objSiswa.RerataUjian
= CDbl(teksRerataUjian.Text)
SemuaSiswa.Add(objSiswa)
End Sub
|
Dapatkah Anda melihat errornya? Satu objek Siswa diciptakan pada baris 2.
Kemudian, pada baris 5-7, properti-propertinya ditugasi nilai-nilai dari
kotak-kotak teks. Pada baris 8, objek ditambahkan ke dalam ArrayList. Tetapi setiap kali loop beriterasi, baris 8 menambahkan objek
Siswa yang sama ke dalam ArrayList. Entri-entri di dalam ArrayList akan mereferensi objek yang
sama, seperti ditunjukkan pada Gambar 3.4. Jadi pelajaran yang diambil dari
contoh ini adalah bahwa Anda harus menciptakan objek baru setiap kali Anda
menyisipkan sebuah objek ke dalam suatu ArrayList.
Gambar 3.4 Ketika anggota-anggota ArrayList mereferensi objek yang sama
Membandingkan Objek-Objek dengan
CompareTo
Ketika Anda mengurutkan array atau ArrayList yang memuat objek-objek dari
kelas sendiri, Anda perlu mendefinisikan bagaimana entri-entri dibandingkan,
menggunakan sebuat metode dengan nama CompareTo.
Metode ini memiliki daftar parameter dan tipe nilai balik berikut:
Function
CompareTo(ByVal obj As Object) As Integer
Jika diberikan dua objek A dan B, metode CompareTo dipanggil seperti ini:
Dim
hasil As Integer = A.CompareTo(B)
Nilai balik dari CompareTo ketika membandingkan dua objek A dan B adalah berikut:
·
Jika A kurang dari B, maka A.CompareTo(B)
menghasilkan sebuah integer negatif.
·
Jika A sama dengan B, maka A.CompareTo(B)
menghasilkan nol.
·
Jika A lebih dari B, maka A.CompareTo(B)
menghasilkan sebuah integer positif.
Jika sebuah kelas tidak memiliki metode CompareTo, semua objek dari kelas itu
tidak dapat diurutkan. Dengan kata lain, objek-objek itu tidak komparabel.
Untuk mendemonstrasikannya, diciptakan kelas Siswa berikut:
Class Siswa
Public
Property Id As String
Public
Property Nama As String
Public Sub
New(ByVal pId As String, ByVal pNama As String)
Id =
pId
Nama =
pNama
End Sub
End Class
Selanjutnya, Anda menyisipkan elemen-elemen
ke dalam ArrayList dan mencoba untuk
mengurutkannya:
Dim list = New ArrayList()
list.Add(New Siswa(“2001”, ”John”))
list.Add(New Siswa(“1004”, ”Kristof”))
list.Add(New Siswa(“1050”, ”Adam”))
list.Sort()
Setelah aplikasi dijalankan, eksepsi yang
tidak tertangani akan pada Gambar 3.5 akan mengatakan: Failed to compare two elements in the array. Dengan kata lain, Anda gagal mencantumkan sebuah
metode CompareTo di dalam kelas Siswa. Tetapi, sebelum menunjukkan
bagaimana menciptakan metode CompareTo,
Anda perlu memahami tentang antarmuka pada pustaka .NET.
Gambar 3.5 Mencoba mengurutkan sebuah ArrayList
Antarmuka
Sebuah antarmuka mendefinisikan sejumlah
metode dan properti yang dapat diimplementasikan oleh kelas-kelas lain. Kelas
yang mengimplementasikan antarmuka akan dijamin memuat metode-metode dan properti-properti
tersebut. Ketika sebuah kelas mengimplementasikan suatu antarmuka, Anda belajar
hal penting tentang kelas: Anda akan belajar apa yang bisa dilakukan oleh kelas
itu.
Antarmuka dideklarasikan dengan cara yang
hampir sama dengan kelas. Sebagai contoh, berikut adalah bagaimana .NET
mendefinisikan antarmuka IComparable:
Interface IComparable
Function CompareTo(ByVal obj As Object) As Integer
End Interface
Perhatikan bahwa metode CompareTo tidak memuat tubuh, hanya sidik metode. Sidik metode
memuat kata Sub atau Function, yang diikuti dengan nama
metode, daftar parameter, dan tipe nilai balik (jika ia adalah sebuah fungsi).
Jika sebuah kelas mengimplementasikan
antarmuka IComparable, kelas itu
harus memuat sebuah metode CompareTo
dengan sidik yang sama dengan yang didefinisikan di dalam antarmuka IComparable. Selain itu, metode CompareTo di dalam kelas
pengimplementasi antarmuka IComparable
harus memuat sebuah tubuh. Selain itu, Anda akan mempelajari bagaimana kelas Siswa dapat mengimplementasikan
antarmuka IComparable.
Contoh CompareTo
Dimisalkan bahwa Anda telah menciptakan kelas
Siswa, dan Anda ingin membandingkan
objek-objek Siswa berdasarkan nomor
ID. Kemudian kelas Siswa tersebut
akan mengimplementasikan antarmuka IComparable.
Kode berikut menunjukkan bagian-bagian yang berelasi dengan antarmuka IComparable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
Class Student
Implements
IComparable
Public
Property Id As String
Public
Property NamaBelakang As String
Public
Sub New(ByVal pId As String, ByVal pNama As String)
Id
= pId
NamaBelakang = pNama
End
Sub
Public Function CompareTo(ByVal obj As
Object) As Integer
Implements IComparable.CompareTo
Dim S As Siswa = CType(obj, Siswa)
Return Me.Id.CompareTo(S.Id)
End Function
End Class
|
Baris 2 menyatakan bahwa kelas ini
mengimplementasikan antarmuka IComparable.
Baris 11 menyatakan bahwa metode CompareTo
di dalam kelas ini mengimplementasikan metode CompareTo yang ditetapkan di dalam antarmuka IComparable. Baris 12 mengkonversi parameter obj menjadi sebuah
objek Siswa, sehingga Anda dapat
mengakses bidang Id pada baris 13.
Pada baris itu, nilai Id dari siswa sekarang (diidentifikasi dengan Me) dibandingkan dengan nilai Id dari siswa yang dilewatkan sebagai
parameter pada metode ini. (Pengkualifikasi Me tidak diharuskan, tetapi ia dapat memperjelas objek mana yang
mana).
Metode CompareTo
tampak sangat mirip pada setiap kelas yang mengimplementasikannya. Hanya
beberapa baris kode yang spesifik dengan tipe objek yang sedang dibandingkan.
Sebagai contoh, jika Anda membandingkan dua objek Akun berdasarkan saldonya, metode CompareTo akan tampak seperti ini:
Public Function CompareTo(ByVal obj As Object) As
Integer
Implements
IComparable.CompareTo
Dim A As
Akun = CType(obj, Akun)
Return
Me.Saldo.CompareTo(A.Saldo)
End Function
Jika Anda berpikir bahwa Anda perlu
mengurutkan sebuah ArrayList, maka
setiap tipe objek yang ditempatkan ke dalam ArrayList tersebut harus merupakan sebuah objek dari suatu kelas
yang mengimplementasikan IComparable.
Aturan yang sama berlaku untuk array yang memuat objek-objek. Hal itu tidak
masalah, karena IComparable mudah
diimplementasikan dan sangat menolong.
Antarmuka IList dan IListSource
Adalah memungkinkan untuk menugaskan sebuah
objek Array, ArrayList, dan List
kepada properti DataSource dari ListBox, tetapi Anda tidak melakukannya
dengan tipe objek lain. Sembarang objek yang ditugaskan kepada properti DataSource harus mengimplementasikan
antarmuka IList atau IListSource. Ketika hal itu terjadi,
kelas Array, ArrayList, dan List
mengimplementasikan IList, yang
memuat metode Contains, Add, IndexOf, Insert, Remove, dan RemoveAt.
Anda dapat pula menugaskan sebuah DataTable kepada properti DataSource dari ListBox karena kelas DataTable
mengimplementasikan antarmuka IListSource.
Membandingkan Objek-Objek dengan
Metode Equals
Anda telah belajar pada Bab 1 bahwa metode Equals membandingkan semua tipe standar
.NET. Ia akan menghasilkan nilai True
jika objek-objek memuat nilai sama. Untuk dua string di bawah ini, ekspresi A.Equals(B) bernilai True:
Dim A As String = “abcde”
Dim B As String = “'abcde”
A.Equals(B) 'True
Tetapi metode Equals tidak secara otomatis dikonfigurasi untuk kelas Anda
sendiri. Contoh kode berikut membandingkan dua objek Siswa. Diasumsikan bahwa Anda belum menciptakan versi dari metode Equals di dalam kelas Siswa. Ekspresi s1.Equals(s2) bernilai False:
Dim s1 As New Siswa(1001)
Dim s2 As New Siswa(1001)
s1.Equals(s2) 'False
Secara natural, adalah sangat menolong untuk
membandingkan objek-objek Siswa atau
objek-objek tipe sendiri lainnya dengan cara yang mudah. Anda bisa saja ingin
melakukan pencarian terhadap objek Siswa
di dalam sebuah ArrayList dengan
memanggil Contains atau IndexOf, misalnya. Untuk melakukannya,
Anda harus mendefinisikan-ulang metode Equals
di dalam kelas Siswa.
Mendefinisikan-Ulang Metode Equals
Untuk mendefinisikan-ulang metode Equals, Anda perlu menciptakan sebuah
metode Equals di dalam kelas Anda
sendiri dengan sidik yang sama dengan metode Equals di dalam kelas Object. Sidik dari metode Equals ditampilkan di sini:
Public Overrides Function Equals(ByVal obj As
Object) As Boolean
Kelas Siswa
berikut memuat sebuah metode Equals
yang membandingkan siswa-siswa berdasarkan nomor ID:
1
2
3
4
5
6
7
8
|
Class Siswa
Public
Property Id As String
Public Property NamaBelakang As String
Public Overrides Function Equals(ByVal obj
As Object) As Boolean
Return Me.Id.Equals(CType(obj, Siswa).Id)
End
Function
End
Class
|
Baris 6 mengkonversi variabel obj menjadi sebuah objek Siswa, dan membaca nilai properti Id dari objek itu. Nilai ini
dibandingkan dengan Me.Id, yaitu ID
dari objek Siswa sekarang (objek
pemanggil). Metode Equals ini
menghasilkan True jika dua siswa
memiliki nomor ID yang sama.
Anda dapat menyeleksi sembarang properti,
variabel, atau nilai terhitung untuk dibandingkan ketika mengimplementasikan
metode Equals. Secara umum, Anda
sebaiknya memilih sebuah properti atau gabungan properti yang akan secara unik
mengidentifikasi tiap objek.
Pada Tutorial 3.2, Anda akan menciptakan
sebuah aplikasi yang menyisipkan objek-objek Siswa ke dalam sebuah ArrayList. Kelas Siswa memuat sebuah metode Equals
yang membandingkan nomor ID.
Tutorial 3.2: Menciptakan sebuah ArrayList yang memuat objek-objek
Siswa
Pada tutorial ini, Anda akan menciptakan
sebuah aplikasi yang menciptakan sebuah ArrayList
yang memuat objek-objek Siswa. Kelas
Siswa akan mengimplementasikan
metode Equals.
Langkah-Langkah
Tutorial
Langkah 1: Buka projek dengan nama Koleksi Siswa.
Langkah 2: Jalankan aplikasi, masukkan nilai-nilai
berikut ke dalam kotak-kotak teks, dan klik tombol Tambahkan ke Koleksi:
ID
Siswa 10000
Nama
Belakang Kristof
Rerata
Ujian 82.5
Langkah 3: Masukkan dua siswa lagi, menggunakan data
berikut, dan klik tombol Tambahkan ke
Koleksi:
10001,
Jonas, 90
10002,
Rumiris, 79.5
Langkah 4: Klik tombol Lihat Semua. Gambar 3.6 menunjukkan keluaran yang diharapkan.
Gambar 3.6 Setelah menyisipkan tiga Siswa ke dalam koleksi
Langkah 5: Selanjutnya, Anda akan melakukan pencarian
siswa berdasarkan nomor ID. Masukkan 10002 ke dalam TextBox di sudut kiri bawah, dan klik pada tombol Cari dengan ID. Program akan mencari
siswa yang cocok dan menampilkannya pada ListBox,
seperti ditunjukkan pada Gambar 3.7.
Gambar 3.7 Setelah melakukan pencarian siswa berdasarkan nomor ID
Langkah 6: Masukkan nomor ID yang tidak ada ke dalam
kotak teks di pojok kiri bawah dari form dan klik tombol Cari dengan ID. Sebuah pesan akan ditampilkan bahwa siswa yang
dicari tidak ada.
Langkah 7: Periksa kode sumber untuk kelas Siswa. Ia
memiliki properti Id, NamaBelakang, RerataUjian, sebuah konstruktor, sebuah metode ToString, dan sebuah metode Equals.
Public
Class Siswa
Public Property Id As String
Public Property NamaBelakang As String
Public Property RerataUjian As Double
Public Sub New(ByVal pId As String,
Optional ByVal pNamaBelakang As String =
"",
Optional ByVal pRerataUjian As Double =
0.0)
Id = pId
NamaBelakang = pNamaBelakang
RerataUjian = pRerataUjian
End Sub
Public Overrides Function ToString() As
String
Return Id & ", " &
NamaBelakang &
", Rerata ujian = " &
RerataUjian.ToString("n2")
End Function
Public Overrides Function Equals(ByVal obj
As Object) As Boolean
Dim lain As Siswa = CType(obj, Siswa)
Return Id = lain.Id
End Function
End
Class
Langkah 8: Periksa kode sumber untuk kelas Form1. Metode tombolTambahkan_Click menciptakan sebuah objek Siswa dan
menambahkannya pada koleksi. Metode tombolLihat_Click
menjelajah koleksi dan menyisipkan setiap item ke dalam ListBox. Metode tombolCari_Click
melakukan pencarian sebuah siswa berdasarkan ID dan menampilkan Siswa yang
cocok pada ListBox.
1
2
3
4
5
6
7
8
9
10
11
12
|
Public
Class Form1
Private semuaSiswa As New ArrayList
Private Sub tombolTambahkan_Click(…)
Handles tombolTambahkan.Click
Try
Dim objSiswa As New
Siswa(teksIDSiswa.Text,
teksNamaBelakang.Text,
CDbl(teksRerataUjian.Text))
semuaSiswa.Add(objSiswa)
Catch
MessageBox.Show("Rerata
ujian tak valid", "Error")
End Try
End Sub
|
Baris 6-7 menciptakan sebuah siswa dari isi
dari kotak-kotak teks, dan baris 8 menyisipkan siswa tersebut ke dalam ArrayList dengan nama semuaSiswa.
Baris 9: Lanjut pada kelas yang sama, lihat handler Click untuk tombol Lihat.
1
2
3
4
5
6
|
Private Sub tombolLihat_Click(…) Handles
tombolLihat.Click
listSiswa.Items.Clear()
For Each sis As Siswa In semuaSiswa
listSiswa.Items.Add(sis.ToString)
Next
End Sub
|
Metode ini membersihkan kotak list dan
menggunakan sebuah statemen For Each
untuk menjelajah ArrayList. Setiap
siswa disisipkan ke dalam kotak list listSiswa.
Langkah 10: Lihat handler Click untuk tombol Cari.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
Private Sub tombolCari_Click(…) Handles
tombolCari.Click
listSiswa.Items.Clear()
Dim S As New Siswa(teksCariID.Text)
Dim indeks As Integer =
semuaSiswa.IndexOf(S)
If indeks <> -1 Then
S = CType(semuaSiswa(indeks),
Siswa)
listSiswa.Items.Add(semuaSiswa(indeks).ToString)
'memperbarui kotak-kotak teks,
agar konsisten
teksIDSiswa.Text = S.Id
teksRerataUjian.Text =
S.RerataUjian.ToString("n")
teksNamaBelakang.Text =
S.NamaBelakang
Else
listSiswa.Items.Add("ID
siswa tidak ditemukan")
End If
End Sub
End
Class
|
Lihat beberapa detil pada kode ini. Baris 3
menciptakan sebuah objek Siswa dari
nomor ID pada kotak teks teksCariID,
dan baris 4 memanggil metode IndexOf
untuk melakukan pencarian siswa di dalam ArrayList.
Jika indeks yang dihasilkan oleh IndexOf
tidak sama dengan 1, maka baris 6 akan membaca sebuah referensi yang menunjuk
ke objek Siswa yang cocok di dalam
list. Karena nilai yang dihasilkan oleh semuaSiswa(indeks)
adalah tipe Object, maka Anda perlu
mengkonversinya menjadi tipe Siswa.
Kemudian, baris 7 menambahkan siswa itu pada kotak list. Baris 9-11 menyalin
nilai-nilai properti siswa ke dalam kotak-kotak teks pada form, sehingga akan
ditampilkan data yang sama seperti pada kotak list.
3.3 Kelas List dan Dictionary
Kelas ArrayList
tidak membatasi tipe-tipe item yang dapat disisipkan ke dalam list. Oleh karena
itu, Anda dapat mengatakan bahwa ArrayList
merupakan koleksi bertipe lemah.
Meskipun ini sepertinya merupakan keuntungan karena ia menawarkan fleksibilitas
untuk menciptakan sebuah koleksi yang memuat pelbagai tipe objek, hal itu dapat
menyebabkan error runtime yang tidak diinginkan. Sebagai contoh, sebuah
aplikasi dapat melemparkan eksepsi jika suatu referensi yang menunjuk ke salah
satu anggota ArrayList berbeda tipe
dari yang diharapkan. Pada kasus itu, pemanggilan terhadap metode CType dapat menyebabkan eksepsi InvalidCastException.
Contoh Eksepsi InvalidCastException
Berikut adalah sebuah contoh yang menunjukkan
bagaimana koleksi tipe lemah di dalam sebuah ArrayList dapat menyebabkan masalah.
Pada kode berikut, objek Siswa dan objek Pekerja
disisipkan ke dalam ArrayList yang
sama dengan nama listKu:
Class Siswa
'...
End Class
Class Pekerja
'...
End Class
Sub Uji()
Dim listKu
As New ArrayList
listKu.Add(New
Siswa)
listKu.Add(New
Pekerja)
'baris
berikutnya akan melemparkan eksepsi
For Each
item As Siswa In listKu
kotakList.Add(item.ToString())
Next
End Sub
Tetapi ketika kode tersebut menjelajah list
dengan statemen For Each, eksepsi InvalidCastException akan dilemparkan.
Gambar 3.8 menunjukkan pesan error yang dihasilkan. Error konversi seperti ini
sangat sulit untuk ditangkap. Aplikasi bisa saja dapat bekerja dengan baik
selama test tertentu. Tetapi di kemudian waktu, suatu runtun masukan tertentu
dapat menyebabkan aplikasi gagal. Tentu ada solusi untuk ini. Anda dapat
mengapit setiap statemen For Each
dengan statemen Try dan Catch yang akan menangkan jenis error
konversi semacam ini. Tetapi hal itu akan menambah pekerjaan dan perencanaan.
Untuk menghindari jenis error konversi seperti ini, bahasa pemrograman modern
mendukung keberadaan koleksi bertipe
kuat.
Gambar 3.8 InvalidCastException
Koleksi Bertipe Kuat
Koleksi bertipe kuat merupakan sebuah koleksi
yang hanya memuat satu tipe objek. Cara yang paling umum untuk
mengimplementasikan koleksi semacam itu adalah melalui penggunaan kelas-kelas
generik, yang dapat ditemukan di dalam namespace Systems.Collections.Generic. Kelas generik adalah sebuah kelas yang
hanya mengampil satu tipe data ketika sebuah objek kelas diciptakan.
Tabel 3.2 menjelaskan sejumlah kelas generik
yang berkaitan dengan list dan kamus, yang akan didemonstrasikan pada bab ini.
Pustaka .NET memuat sejumlah kelas generik, yang dapat Anda baca pada
dokumentasi online pada http://msdn.microsoft.com.
Tabel 3.2 Kelas-kelas di dalam namespace System.Collections.Generic
Kelas atau
Struktur
|
Penjelesan
|
List(Of
Tipe)
Dictionary(Of
TipeKunci, TipeNilai)
SortedDictionary(Of
TipeKunci, TipeNilai)
KeyValuePair(Of
TipeKunci, TipeNilai)
|
Sebuah list
sekuensial yang memuat objek-objek yang bertipe sama.
Sebuah
kelas yang merepresentasikan koleksi kunci dan nilai. Kunci harus unik.
Setiap nilai berkaitan dengan satu kunci.
Sebuah
kamus dimana di dalamnya kunci-kunci ditata secara terurut.
Merepresentasikan
sebuah entri Dictionary.
|
List (Of Tipe)
List(Of Tipe) adalah sebuah kelas yang memuat koleksi item
sekuensial bertipe kuat. Kelas ini dipakai sebagai pengganti kelas ArrayList, yang memiliki metode-metode
dan properti-properti yang hampir sama dengan kelas ArrayList. Kelas List(Of
Tipe) menegakkan pemeriksaan tipe yang tegas pada item-item yang Anda
sisipkan ke dalamnya. Tabel 3.3 mencantumkan sejumlah properti dan metode dari
kelas ini.
Tabel 3.3 Sejumlah properti dan metode dari kelas List(Of Tipe)
Properti Atau Metode
|
Penjelasan
|
Add(elemen
As Tipe)
Clear(
)
Contains(elemen
As Tipe) As Boolean
Count(
) As Integer
Insert(indeks
As Integer, elemen as Tipe)
Item(
indeks As Integer ) As Tipe
Remove(
elemen As Tipe)
RemoveAt(
indeks As Integer )
Sort()
ToArray()
|
Menambahkan
sebuah item di akhir list
Menghapus
semua item dari list
Menghasilkan
True jika list memuat item yang
ditentukan
Menghasilkan
banyak item di dalam list
Menyisipkan
sebuah item ke dalam list pada posisi indeks tertentu.
Menghasilkan
sebuah referensi yagn menunjuk ke item list pada posisi indeks tertentu.
Menghapus
kemunculan pertama dari item tertentu dari list.
Menghapus
item pada posisi indeks tertentu.
Mengurutkan
list.
Menghasilkan
sebuah array bertipe kuat yang memuat objek-objek dari ArrayList.
|
Contoh: List
yang memuat integer-integer
Kode berikut mendeklarasikan sebuah objek List(Of Integer) dan menambahkan tiga
integer pada list tersebut:
Dim intList As New List(Of Integer)
intList.Add(30)
intList.Add(10)
intList.Add(20)
Metode Clear
menghapus semua item.
intList.Clear()
Properti Item
membaca sebuah referensi ke suatu item list, menggunakan indeks untuk
mengidentifikasi posisi item:
Dim X As Integer = intList.Item(1)
Statemen For
Each menjelajah sebuah List.
Kode berikut menyalin item-item List
ke dalam sebuah ListBox:
For Each M As Integer In intList
kotakList.Items.Add(M)
Next
Metode Contains
menghasilkan True jika ditemukan
sebuah nilai yang cocok:
Dim
ditemukan As Boolean = intList.Contains(20)
Metode IndexOf
menghasilkan posisi indeks dari sebuah item cocok, atau -1 jika item tidak
ditemukan:
Dim indeks As Integer = intList.IndexOf(20)
Metode Remove
menghapus item yang cocok. Jika nilai tidak ditemukan, statemen tidak melakukan
apapun:
intList.Remove(30)
Metode RemoveAt
menghapus sebuah item pada posisi indeks yang diberikan:
intList.RemoveAt(0)
Metode Sort
mengurutkan elemen-elemen dengan tatanan menaik:
intList.Sort()
Metode ToArray
menghasilkan sebuah array yang memuat item-item list:
intList.ToArray()
Kelas List
memuat banyak metode lain, yang dapat Anda baca pada dokumentasi MSDN online.
Pengurutan dengan Komparator
Kadangkala, Anda ingin mengurutkan sebuah List dengan cara yang tidak standar,
seperti pengurutan dengan tatanan menurun. Atau, Anda ingin mengururkan
properti lain selain yang digunakan oleh metode CompareTo. Untuk melakukannya, Anda perlu mendefinisikan sebuah
metode dengan nama komparator, yang membandingkan elemen-elemen pada kedua list
berdasarkan apa yang Anda butuhkan. Metode tersebut harus mengikut bentuk umum
berikut:
Public
Function NamaMetode(ByVal nil1 As Tipe, ByVal nil2 As
Tipe) As Integer
Anda dapat menggunakan sembarang pengenal
yang Anda suka untuk NamaMetode, nil1, dan nil2. Dua parameter tersebut merepresentasikan pasangan-pasangan
nilai yang akan dibandingkan selama proses pengurutan. Tipe pada bentuk umum ini harus cocok dengan tipe objek di dalam List.
Fungsi-fungsi pengurutan selalu melakukan
perbandingan antara pasangan-pasangan atau item-item. Komparator itu sendiri
tidak mengurutkan list, karena Anda masih perlu memanggil metode Sort dari kelas List. Anda hanya perlu memberitahu metode Sort bagaimana item-item
list dibandingkan.
Contoh Komparator Siswa
Dimisalkan bahwa Anda ingin mengurutkan
sebuah list yang memuat objek-objek Siswa.
Anda mengasumsikan bahwa kelas Siswa
telah memuat sebuah metode CompareTo
yang membandingkan objek-objek Siswa
berdasarkan nomor ID. Anda sekarang bisa menciptakan list yang memuat
objek-objek Siswa dan memanggil
metode Sort:
Dim siswaList As New List(Of Siswa)
siswaList.Add(New Siswa(1234, “Jonas”));
siswaList.Add(New Siswa(4023, “Bakri”));
siswaList.Add(New Siswa(5612, “Gonzalez”));
siswaList.Add(New Siswa(1001, “Chong”));
siswaList.Sort()
List sekarang diurutkan dengan tatanan menaik
berdasarkan nomor ID:
1001 Chong
1234 Jonas
4023 Bakri
5612 Gonzalez
Tetapi, jika Anda juga ingin mengurutkan list
dengan tatanan menaik berdasarkan nama belakangnya, Anda perlu lebih dahulu
menciptakan sebuah komparator yang membandingkan properti NamaBelakang dari objek-objek:
Public Function BandingkanNama(ByVal X As Siswa,
ByVal Y As Siswa) As Integer
Return X.NamaBelakang.CompareTo(Y.
NamaBelakang)
End Function
Kemudian Anda akan mengurutkan list dengan
melewatkan alamat dari komparator kepada metode Sort:
siswaList.Sort(AddressOf BandingkanNama)
Setelah pengurutan, list yang memuat
siswa-siswa akan diurutkan secara menaik berdasarkan nama belakangnya:
4023 Bakri
1001 Chong
5612 Gonzalez
1234 Jonas
Dictionary(Of TipeKunci, TipeNilai)
Kelas Dictionary(Of
TipeKunci, TipeNilai) memetakan suatu himpunan kunci dengan sebuah himpunan
nilai. Dengan kata lain, setiap kunci di dalam kamus memiliki satu nilai yang
berkaitan dengan kunci itu. Kunci-kunci harus unik, tetapi nilai-nilai boleh
tidak unik (boleh duplikat). Sebuah Dictionary dioptimasi untuk pencarian
terhadap himpunan kunci yang besar. Jika Anda memiliki 20 juta item di dalam
sebuah Dictionary, misalnya, kunci
dari satu item akan dicari dengan sesaat.
Adalah penting untuk memilih properti yang
tepat pada kelas Anda untuk digunakan sebagai kunci Dictionary. Anda perlu mencari sebuah properti dengan nilai unik
untuk setiap item yang Anda sisipkan di dalam Dictionary. Jika Anda menyisipkan pekerja-pekerja, misalnya,
properti ID dari kelas Pekerja
mungkin merupakan pilihan yang baik untuk dijadikan kunci. Di sisi lain,
properti NamaBelakang bukanlah
pilihan kunci yang baik karena dua pekerja bisa saja memiliki nama belakang
(marga) yang sama.
Kelas-kelas dari kunci-kunci kamus harus
mengimplementasikan antarmuka IComparable,
dan mereka harus mendefinisikan-ulang metode Equals. Oleh karena itu, adalah sangat mudah untuk menggunakan tipe
data standar .NET sebagai sebuah kunci Dictionary.
Pilihan yang umum adalah Integer dan String. Nilai-nilai terkait dengan kunci
dapat bertipe data apa saja, tidak ada pembatasan spesial.
Menciptakan Sebuah Dictionary
Ketika Anda mendeklarasikan sebuah objek Dictionary, Anda perlu menyediakan
tipe-tipe data untuk pasangan kunci dan nilai. Bentuk umumnya adalah berikut:
Dim
namaVar As New Dictionary(Of tipekunci, tipenilai)
Sebagai contoh, kode berikut mendeklarasikan
sebuah Dictionary dengan nama gaji,
menggunakan Integer sebagai kunci
dan Decimal sebagai nilai yang
berkaitan dengan kunci:
Dim gaji As New Dictionary(Of Integer, Decimal)
Menambahkan Entri ke dalam Sebuah
Dictionary
Metode Add
menambahkan sepasang kunci/nilai ke dalam sebuah Dictionary. Kode berikut, misalnya, menambahkan beberapa ID pekerja
dan nilai-nilai gaji ke dalam Dictionary
dengan nama gaji:
gaji.Add(3001, 50000D)
gaji.Add(2020, 45000D)
gaji.Add(3125, 64500D)
gaji.Add(2501, 32800D)
Ketika menyisipkan pasangan-pasangan kunci/nilai,
tipe datanya harus sesuai dengan tipe-tipe data yang digunakan saat
mendeklarasikan Dictionary. Inilah
mengapa Anda mengatakan Dictionary
sebagai koleksi bertipe data kuat. Statemen berikut adalah statemen yang salah,
karena ia mencoba menyisipkan sebuah kunci string dan sebuah gaji bertipe Double:
gaji.Add(“1002”, 34000.2)
Di sisi lain, Anda dapat melewatkan sebuah
integer sebagai argumen kedua karena integer secara otomatis dikonversi menjadi
Decimal:
Dim N As Integer = 35000
gaji.Add(“1002”, N)
Jadi, lebih tepatnya, tipe-tipe argumen harus
kompatibel dengan tipe-tipe parameter dari metode Add.
Properti Count
mengindikasikan banyaknya entri di dalam Dictionary.
Statemen berikut menugaskan banyaknya entri kepada sebuah Label:
labelBanyak.Text
= “Terdapat ” & gaji.Count & ” entri”'
Metode Clear
menghapus semua entri dari sebuah Dictionary.
Menjejak Entri-Entri Dictionary
Setiap entri di dalam sebuah Dictionary merupakan sebuah objek KeyValueObject, yang memuat dua
properti: Key dan Value. Ketika Anda mendeklarasikan
sebuah KeyValuePair, Anda perlu
spesifik dalam menyebutkan tipe data dari kunci dan nilai. Berikut adalah
bagaimana Anda mendeklarasikannya untuk Dictionary
dengan nama gaji:
Dim entri As KeyValuePair(Of Integer, Decimal)
Kemudian, Anda dapat menggunakan variabel entri ketika mengkode statemen For Each. Entri itu memuat kunci dan nilai dari tiap entri Dictionary. Kode berikut menambahkan
beberapa entri ke dalam kamus gaji
dan kemudian menyalin entri-entri tersebut ke dalam sebuah ListBox:
gaji.Add(3001, 50000D)
gaji.Add(2020, 45000D)
gaji.Add(3125, 64500D)
gaji.Add(2501, 32800D)
For Each entry In gaji
kotakList.Items.Add(entri.Key
& “-->” & entri.Value)
Next
Loop tersebut menghasilkan keluaran berikut:
3001-->50000
2020-->45000
3125-->64500
2501-->32800
Mencari, Memodifikasi, dan Menghapus
Entri
Anda tidak dapat menggunakan indeks integer
untuk mengakses posisi tertentu di dalam sebuah kamus. Untuk mencari entri Dictionary, Anda harus melewatkan kunci
yang ingin dicari kepada properti Item.
Statemen berikut menghasilkan 45000, gaji dari pekerja dengan nomor ID 2020:
Dim pendapatan As Decimal = gaji.Item(2020)
Jika Anda mencoba membaca nilai yang
berkaitan dengan kunci yang tidak ada, maka properti Item akan melemparkan eksepsi KeyNotFoundException.
Jika Anda menugaskan sebuah nilai kepada
properti Item dan mereferensi sebuah
kunci yang ada, maka Dictionary akan
mengganti nilai yang berkaitan dengan kunci tersebut. Sebagai contoh, statemen
berikut mengganti gaji dari pekerja dengan ID 3001:
gaji.Item(3001) = 62000D
Jika Anda menugaskan sebuah nilai kepada
properti Item dan mereferensi sebuah
kunci yang tidak ada di dalam Dictionary,
maka sebuah entri baru akan diciptakan dan disisipkan. Statemen berikut
menyisipkan sebuah entri baru ke dalam Dictionary,
dengan mengasumsikan bahwa kunci 2025 tidak ada:
gaji.Item(2025)
= 72000D
Metode Remove menghapus entri dengan kunci
cocok dengan parameter masukan metode. Bentuk umumnya adalah:
namaKamus.Remove(kunci) As
Boolean
Jika kunci ditemukan dan item dihapus, maka Remove akan menghasilkan True. Sebaliknya, Remove menghasilkan False.
Sebagai contoh, statemen berikut menghapus entri dengan kunci 3125:
gaji.Remove(3125)
Metode Ekstensi
Metode ekstensi adalah suatu fitur di dalam
NET yang dapat dipakai developer menambahkan metode baru pada kelas yang telah
ada. Kelas Dictionary memiliki
sejumlah banyak metode yang berkaitan dengan koleksi kunci dan nilanya. Berikut
adalah beberapa di antaranya yang dicantumkan pada Tabel 3.4:
Dim
rerata As Decimal = gaji.Values.Average()
Dim
jum as Decimal = gaji.Values.Sum()
Dim minNil
As Decimal = gaji.Values.Min()
Tabel 3.4 Metode-metode ekstensi di dalam Dictionary
Metode Ekstensi
|
Penjelasan
|
Values.Average
Values.Sum
Values.ToArray
Values.Max
Values.Min
Keys.Max
Keys.Min
|
Menghasilkan
rerata dari nilai-nilai.
Menghasilkan
penjumlahan atas nilai-nilai.
Menghasilkan
sebuah array yang memuat nilai-nilai.
Menghasilkan
nilai terbesar.
Menghasilkan
nilai terkecil.
Menghasilkan
kunci terbesar.
Menghasilkan
kunci terkecil.
|
Kelas SortedDictionary
SortedDictionary adalah sebuah kamus yang mempertahankan
kunci-kuncinya dengan urutan spesifik. Berikut adalah contohnya:
Dim
gajiTerurut As New SortedDictionary(Of Integer, Decimal)
Semua metode dan properti yang telah
didiskusikan untuk kelas Dictionary
berlaku juga untuk kelas SortedDictionary.
Anda dapat melewatkan sebuah objek Dictionary yang telah ada kepada
konstruktor dari sebuah objek SortedDictionary,
sepanjang tipe data dari kunci dan nilainya sama. Sebagai contoh, statemen
berikut membuat salinan dari kamus gaji
ketika menciptakan gajiTerurut:
Dim
gajiTerurut As New SortedDictionary(Of Integer, Decimal)
(gaji)
Tutorial 3.3: Menciptakan Sebuah Konkordansi Teks
Pada tutorial
ini, Anda akan menciptakan sebuah aplikasi yang membangun konkordansi, yaitu
sebuah katalog kata yang ditemukan pada sebuah dokumen. File masukan berupa
sebuah file teks yang memuat kata-kata yang dipisahkan dengan spasi. Himpunan
kata akan disimpan sebagai koleksi kunci di dalam sebuah objek Dictionary, dan tiap nilai yang
berkaitan dengan kunci berupa sebuah List(Of
Integer) yang memuat nomor-nomor baris dimana kata ditemukan di dalam file
masukan. Dictionary akan
dideklarasikan seperti ini:
Private kamusKata As New Dictionary(Of String, List(Of Integer))
Ketika
aplikasi dijalankan, user akan memilih perintah Buka dari menu File,
seperti ditunjukkan pada Gambar 3.9. Sebuah kontrol OpenFileDialog akan ditampilkan dan user akan memilih file masukan.
File dibaca ke dalam sebuah list string, dan setiap kata dari file disisipkan
ke dalam kamus.
Gambar 3.9 Saat aplikasi dijalankan, user memilih file
masukan
Pada Gambar
3.10, aplikasi sekarang telah siap untuk digunakan. User dapat mengetikkan satu
kata dan mengklik tombol Cari untuk melihat semua baris dari file yang memuat
kata tersebut (Gambar 3.11). File yang digunakan pada kasus ini adalah novel
Moby Dick karya Herman Melville.
Gambar 3.10 File masukan dimuat dan siap untuk digunakan
Jika user
mengklik tombol Semua, keseluruhan kata di dalam kamus akan ditampilkan pada
sebuah kotak list kolom-jamak (Gambar 3.12).
Sebelum
menciptakan aplikasi, Anda perlu mempelajari kontrol OpenFileDialog.
Kontrol OpenFileDialog
Kontrol OpenFileDialog dapat dipakai user untuk
memilih sebuah file pada jendela Windows standar. Ia memiliki properti InitialDirectory agar dialog dapat
menuju ke direktori tertentu ketia ia dibuka. Diasumsikan bahwa kontrol itu dinamai
dengan ofdBukaFile. Statemen berikut
menugaskan kepadanya nilai direktori terkini dari aplikasi, yang dihasilkan
oleh metode GetCurrentDirectory:
ofdBukaFile.InitialDirectory =
Directory.GetCurrentDirectory()
Selain itu,
Anda dapat meminta dialog untuk hanya menampilkan tipe file tertentu dengan
menetapkan properti Filter dengan
deskripsi tertentu, dipisahkan dengan batang vertikal dari nama wildcard
(*.txt):
ofdBukaFile.Filter = “File Teks|*.txt”
Metode ShowDialog menampilkan jendela dialog.
User dapat mengklik tombol Open atau
Cancel untuk menutup jendela. Metode
ini menghasilkan sebuah nilai DialogResult
yang dapat Anda pakai untuk mengetahui tombol mana yang diklik:
Dim hasil As DialogResult = ofdBukaFile.ShowDialog()
Statemen If dapat dipakai untuk memeriksa apakah
tombol Open telah diklik (dengan
nilai DialogResult.OK):
If hasil = DialogResult.OK Then
Jika file
telah dipilih, properti FileName
akan memuat path utuh dari file.
Kontrol OpenFileDialog memiliki metode OpenFile yang membuka file yang dipilih
oleh user dan menghasilkan sebuah objek System.IO.Stream.
Anda dapat melewatkan objek itu kepada konstruktor kelas StreamReader, sehingga aplikasi dapat menggunakan variabel infile untuk membaca baris-baris data
dari file.
Dim infile As StreamReader = New StreamReader(ofdBukaFile.OpenFile())
Memfilter String
Ketika
membaca kata-kata dari file masukan pada tutorial ini, Anda akan menghapus
semua tanda baca seperti koma dan titik. Anda dapat mendefinisikan sebuah
string yang memuat sejumlah karakter tanda baca dan mengkonversinya menjadi
sebuah array karakter:
Dim buangKarakter As Char() =
("?':;.,!""").ToCharArray()
Selanjutnya,
ketika Anda membaca sebuah kata dari file, Anda dapat memanggil metode TrimEnd, melewatkannya array karakter
yang memuat sejumlah karakter tanda baca tersebut:
kata = kata.TrimEnd(buangKarakter)
Jadi, sebuah
kata seperti “Street;” akan dikonversi menjadi “Street”. Anda dapat pula
mengkonversi kata masukan menjadi huruf kecil, yang membuatnya lebih mudah
untuk mencari kecocokan kata:
kata = kata.ToLower()
Ketika
memeriksa sebuah kata, Anda ingin mengetahui apakah karakter pertama adalah
sebuah huruf atau bukan. Kelas Char
memiliki metode untuk melakukannya yang menghasilkan nilai True atau False:
If Char.IsLetter(kata(0)) Then ...
Langkah-Langkah Tutorial
Langkah 1: Ciptakanlah sebuah aplikasi baru dengan nama Pencarian Teks.
Langkah 2: Salin file dengan nama mobydick.txt ke dalam folder projek Anda.
Langkah 3: Tambahkan kontrol-kontrol seperti dicantumkan pada
Tabel 3.5 pada form. Lihat kembali Gambar 3.9 untuk lokasi dari tiap kontrol.
Kontrol DropDownButton pada
toolstrip memuat menu File dengan
dua sub item: Buka dan Keluar. Toolstrip juga memuat beberapa
separator.
Tabel 3.5 Kontrol-kontrol pada aplikasi Pencarian Teks
Tipe
Kontrol
|
Nama
Kontrol
|
Properti
|
Form
ToolStrip
ListBox
ToolStripLabel
ToolStripTextBox
ToolStripDropDownButton
ToolStripMenuItem
ToolStripMenuItem
ToolStripButton
ToolStripButton
OpenFileDialog
|
kotakList
labelNamaFile
teksCariKata
mnuFileBuka
mnuFileKeluar
tombolCari
tombolSemua
ofdBukaFile
|
Text:
Pencarian Teks
ColumnWidth:
100
Text:
(Tidak ada file)
Text: Buka
Text:
Keluar
Text: Cari
Text: Semua
|
Langkah 4: Buka jendela Code
dari form startup dan tambahkan statemen Imports
di atas kelas sebagai berikut:
Imports System.IO
Langkah 5: Di dalam kelas, sisipkan deklarasi-deklarasi berikut:
Private infile As StreamReader
Private kamusKata As New Dictionary(Of
String, List(Of Integer))
Private teksMentah As New List(Of String)
Variabel teksMentah memuat semua baris masukan
dari file, sehingga Anda dapat menampilkan baris-baris ini pada kotak list
ketika user melakukan pencarian kata.
Langkah 7: Tambahkan fungsi BukaFileMasukan,
yang menghasilkan True jika sebuah
file diseleksi oleh user.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Private
Function BukaFileMasukan() As Boolean
'menampilkan kontrol OpenFileDialoh dan
membiarkan user
'memilih file masukan
With ofdBukaFile
.InitialDirectory =
Directory.GetCurrentDirectory()
.FileName = "*.txt"
Dim hasil As DialogResult = .ShowDialog()
If hasil = DialogResult.OK Then
infile = New StreamReader(.OpenFile())
labelNamaFile.Text = "Nama File: "
&
Path.GetFileName(.FileName)
Return True
Else
Return False
End If
End With
End
Function
|
Baris 10
menyalin nama file dari kontrol OpenFileDialog
ke dalam sebuah label pada toolstrip. Pemanggilan terhadap Path.GetFileName menghasilkan nama file setelah membuang semua path
direktori.
Langkah 7: Selanjutnya, tambahkan event handler Click untuk perintah menu File | Buka:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
Private
Sub mnuFileBuka_Click(…) Handles mnuFileBuka.Click
'user mengklik item menu File | Buka
If Not BukaFileMasukan() Then Return
'membaca tiap baris dan menyisipkan tiap
kata ke dalam kamus
'Untuk setiap kata yang ada, tambahkan
nomor baris
'pada list untuk entri kata tersebut
Dim nomorBaris As Integer = 0
Dim buangKarakter As Char() =
("?':;.,!""").ToCharArray()
Do While Not infile.EndOfStream()
Dim temp As String =
infile.ReadLine()
If temp.Trim().Length = 0 Then
Continue Do
teksMentah.Add(temp)
Dim kataArr() As String =
temp.Split(" "c)
For Each kata As String In kataArr
kata =
kata.TrimEnd(buangKarakter).ToLower()
If kata.Length > 0 AndAlso
Char.IsLetter(kata(0)) Then
If Not
kamusKata.ContainsKey(kata) Then
kamusKata.Add(kata, New
List(Of Integer))
End If
kamusKata(kata).Add(nomorBaris)
End If
Next
nomorBaris += 1
Loop
End Sub
|
Ini merupakan
metode yang panjang, jadi Anda perlu hati-hati. Baris 3 memanggil OpenInputFile, dan keluar jika user
membatalkan dialog. Baris 8 menciptakan sebuah variabel dengan nama nomorBaris, yang akan menjejak baris
yang dibaca paling terakhir dari file. Baris 11 mengulangi loop sampai akhir
file. Baris 12 membaca sebaris data dari file, dan baris 15 menambahkan baris
tersebut pada list teksMentah yang
telah dideklarasikan sebelumnya. Baris 13 melompati sisa loop jika sebaris
kosong ditemukan dan kembali lagi ke baris 11. Baris 16 memecah baris masukan
menjadi sebuah array yang memuat kata-kata.
Baris 18
memulai sebuah loop baru dengan pekerjaan untuk mengambil setiap kata di dalam
array, memotongnya dan mengkonversinya menjadi huruf kecil (baris 19), dan
memastikan bahwa ia tidak kosong dan bahwa ia diawali dengan huruf (baris 20).
Kemudian pada baris 21, Anda memeriksa apakah kata telah ada di dalam kamus.
Jika tidak, Anda menambahkan kata itu ke dalam kamus (baris 22) dan
memberikannya sebuah nomor baris kosong. Pada baris 24, Anda menambahkan nomor
baris terkini pada list yang berkaitan dengan kata terkini. Baris 27
menginkremen nomor baris dan loop kembali membaca baris lain dari file (baris
12).
Langkah 8: Tambahkan sebuah event handler Click untuk tombol Semua,
yang menampilkan semua kata di dalam kamus.
1
2
3
4
5
6
7
8
|
Private
Sub tombolSemua_Click(…) Handles tombolSemua.Click
kotakList.MultiColumn = True
kotakList.Items.Clear()
For
Each entri As KeyValuePair(Of String,
List(Of Integer)) In kamusKata
kotakList.Items.Add(entri.Key)
Next
End Sub
|
Perhatikan
bagaimana kode tersebut menetapkan properti MultiColumn pada kotak list untuk
menampilkan sebanyak mungkin kata pada saat yang bersamaan.
Langkah 9: Ciptakanlah handler Click untuk tombol Cari.
Pekerjaannya adalah mencari kata di dalam kamus dan menampilkan semua baris
yang cocok dari list teksMentah.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Private
Sub tombolCari_Click(…) Handles tombolCari.Click
kotakList.MultiColumn = False
kotakList.Items.Clear()
If
kamusKata.ContainsKey(teksCariKata.Text) Then
For Each nomorBaris As Integer In
kamusKata(
teksCariKata.Text)
kotakList.Items.Add(nomorBaris &
":" & vbTab &
teksMentah(nomorBaris))
Next
Else
kotakList.Items.Add("(kata tidak
ditemukan)")
End
If
End Sub
|
Baris 4
memanggil metode ContainsKey untuk
mencaritahu apakah kata (pada teksCariKata.Text)
ada di dalam kamus atau tidak. Tipe pencarian ini dieksekusi sangat cepat. Jika
kata ditemukan, maka ekspresi berikut menghasilkan sebuah objek List(Of Integer) yang memuat
nomor-nomor baris diman kata itu ditemukan pada file masukan:
kamusKata(teksCariKata.Text)
Baris 5 menjelajak
list yang memuat nomor-nomor baris. Baris 7 menggunakan setiap nomor baris
sebagai indeks ke dalam objek list teksMentah,
dan menyisipkan baris teks ke dalam kotak list. Terakhir, jika kata yang
dimasukkan user tidak ditemukan, baris 11 akan menampilkan pesan kegagalan pada
kotak list.
Langkah 10: Terakhir, sisipkan event handler Click untuk item menu File | Keluar.
Private Sub mnuFileKeluar_Click(…) Handles
mnuFileKeluar.Click
Me.Close()
End Sub
Langkah 11: Simpan projek dan jalankan aplikasi. Buka file mobydick.txt dari direktori projek.
Klik tombol Semua untuk menampilkan
semua kata yang ditemukan di dalam file.
Langkah 12: Masukkan sebuah kata ke dalam kotak teks yang ingin
Anda cari, dan klik tombol Cari. Anda akan melihat sejumlah baris dari file
yang memuat kata itu.
3.4 LINQ (Language Integrated Query)
LINQ (Language Integrated Query) adalah
sebuah bahasa query yang dibangun ke dalam .NET yang dapat dipakai untuk
menampilkan informasi dari sejumlah tipe berbeda dari sumber data. Sebagai
contoh, LINQ dapat melakukan query terhadap koleksi yang memuat objek-objek
(array, List, ArrayList) di dalam memori, database, file XML, Excel, dan lainnya.
Sekelompok orang cerdas di Microsoft memiliki
ide cemerlang: Jika SQL merupakan bahasa yang tanggun untuk pencarian (query)
dalam database, mengapa tidak menemukan jenis bahasa yang sama di dalam .NET
yang dapat melakukan query terhadap sejumlah tipe data, bukan hanya database?
Dan demikianlah, LINQ ditemukan. Pada bab ini, Anda akan dikenalkan tentang
tipe sederhana dari LINQ yang dikenal dengan LINQ untuk objek.
Query LINQ paling sederhana mencakup empat
klausa: From, Where, Select, dan Order By:
·
From: Mengidentifikasi
sumber data, yang dapat berupa objek seperti array atau List.
·
Where (opsional): Memuat
sebuah ekspresi Boolean yang menyeleksi nilai-nilai mana yang akan disalindari sumber data.
·
Select: Mengidentifikasi nama dari bidang
(bidang-bidang) yang akan dihasilkan oleh query.
·
Order By (opsional): Mengindikasikan bagaimana hasil
query diurutkan.
Contoh Array
Anda akan mempelajari bagaimana menggunakan
LINQ untuk mengquery sebuah array yang memuat sejumlah integer. Perhatikan
deklarasi array berikut:
Dim
intNilai() As Integer = {4, 104, 2, 102, 1, 101, 3, 103}
Statemen LINQ berikut menghasilkan semua
nilai array yang lebih besar dari 100:
Dim
query = From item In intNilai
Where
item > 100
Select
item
Lihat statemen tersebut lebih detil. Pertama,
perhatikan bahwa statemen tersebut diawali dengan Dim query. Anda sedang
mendeklarasikan sebuah objek dengan nama query yang mendefinisikan sebuah query LINQ, tetapi Anda belum
menetapkan sebuah tipe data. Visual Basic secara otomatis menentukan tipe data
untuk objek, suatu teknik yang dikenal dengan inferensi tipe.
Di sisi kanan dari operator = adalah definisi
query, yang memeriksa setiap item di dalam array intNilai untuk melihat apakah nilainya lebih besar dari 100, dan
jika ya, klausa Select memilih nilai
tersebut.
From
item In intNilai
Where
item > 100
Select
item
Setelah query didefinisikan, Anda dapat
menggunakannya dengan pelbagai cara. Anda dapat menjelajahnya, Anda dapat
membangun query lain dari query tersebut, atau Anda dapat melewatkan query ke
metode lain.
Sebagai contoh, segmen kode berikut
menjelajah query dan menambahkan tiap nilainya pada sebuah kotak list dengan
nama listHasil:
For
Each intNil As Integer In query
labelHasil.Items.Add(intNil)
Next
Karena array intNilai memuat {4, 104, 2, 102, 1,
101, 3, 103}, maka query
akan menampilkan nilai 104, 102, 101, dan 103 pada kotak list, dengan urutan
tersebut.
Untuk mengurutkan hasil dari query LINQ
dengan tatanan menaik, Anda dapat menggunakan operator Order By, seperti
ditunjukkan di sini:
Dim
query = From item In intNilai
Where
item > 100
Select
item
Order
By item
LINQ menggunakan operator seperti Where, Select, dan Order By, yang sama dengan operator pada
bahasa query database SQL. Operator-operator tersebut merupakan bagian dari
Visual Basic dan dapat diperiksa hasilnya oleh kompiler sebelum aplikasi
dijalankan. Ini akan mempermudah untuk
mengetahui bila Anda telah melakukan kesalahan.
Contoh: Menyeleksi Integer-Integer
Genap dari Array
Pada contoh ini, Anda melakukan query
terhadap sebuah array yang memuat sejumlah integer, untuk mencari nilai-nilai
genap (yang habis dibagi oleh 2). Selain itu, Anda akan mengurutkannya dengan
tatanan menaik:
Dim
angka() As Integer = {4, 3, 2, 1, 6, 9, 7}
Dim
queryGenap = From nil In angka
Where
(nil Mod 2 = 0)
Order
By nil
Select
nil
Ekspresi nil
Mod 2 menghasilkan sisa setelah pembagian nil dengan 2. Jika sisanya nol, nilai tersebut pasti genap.
Nilai-nilai yang dihasilkan oleh queryGenap
adalah {2, 4, 6}.
Anda dapat memodifikasi sebuah query setelah
ia diciptakan. Sebagai contoh, statemen berikut membalik urutan dari
nilai-nilai yang dihasilkan oleh queryGenap:
queryGenap
= queryGenap.Reverse()
Apa tipe dari queryGenap? Ia didefinisikan sebagai antarmuka bertipe kuat dengan
nama IOrderedEnumerable(Of Integer).
Hal penting di sini adalah bahwa elemen-elemen yang dihasilkan oleh query ini
“mengetahui” bahwa ia adalah integer.
Membangun Query dar Query yang telah
Ada
queryGenap menghasilkan nilai-nilai genap {2, 4, 6).
Anda dapat membangun sebuah query kedua yang lebih lanjut membatasi nilai-nilai
yang dihasilkan oleh queryGenap.
Query dengan nama genapBesar berikut
menghasilkan satu nilai 6:
Dim
genapBesar = From nil in queryGenap
Where
nil > 4
Select nil
Properti dan Metode Ekstensi
Metode ekstensi adalah sebuah metode yang
menghasilkan sebuah versi termodifikasi dari keluaran dari sebuah query LINQ.
Metode ekstensi semacam itu adalah Count:
queryGenap.Count()
Adalah penting untuk menyadari bahwa queryGenap tidak memuat data aktual. Ia
adalah sebuah variabel yang memuat sebuah query. Anda dapat memodifikasi query,
melewatkan variabel sebagai parameter, atau menugaskannya kepada variabel lain.
LINQ menggunakan eksekusi deferensi, yang berarti bahwa sebuah query LINQ tidak
dieksekusi sampai Anda menggunakannya. Hal ini terjadi ketika Anda mengisi
sebuah kotak list dengan nilai-nilai dari query atau menggunakan item-item
dengan cara lain.
Pada kode berikut, Anda menyalin sejumlah
nilai keluaran yang dihasilkan oleh queryGenap
ke sebuah ListBox dan kemudian
menampilkan nilai rerata dari integer-integer yang dihasilkan oleh queryGenap:
For
Each angka In queryGenap
kotakList.Items.Add(angka.ToString())
Next
'menampilkan
nilai rerata dari queryGenap
labelRerata.Text
= “Rerata = “ & queryGenap.Average()
Melakukan Query Terhadap Sebuah List
yang Memuat Objek-Objek
LINQ mempermudah untuk melakukan query
terhadap list dan kamus yang memuat sejumlah objek. Khususnya, Anda dapat
mengakses properti-properti objek berdasarkan nama. Untuk melihat bagaimana hal
ini dilakukan, Anda akan menciptakan sebuah List(Of Siswa) dan merancang query-query LINQ yang diterapkan pada
list tersebut. Anda akan mengasumsikan bahwa kelas Siswa telah didefinisikan,
dan ia memiliki sebuah konstruktor dengan parameter-parameter:
Public
Class Siswa
Public Property Id As String
Public Property NamaBelakang As String
Public Property Status As Integer ‘nilai:
1,2,3,4
Public Property Ipk As Double ‘indeks
prestasi kumulatif
Public Property Jurusan As String
‘dan lainnya
End
Class
Anda dapat mengisi sebuah List dengan objek-objek Siswa, sebagai berikut:
Dim
daftarSiswa As New List(Of Siswa)
With
daftarSiswa
.Add(New Siswa("1241",
"Kristof", 1, 3.2, "BIO"))
.Add(New Siswa("1641",
"Bakri", 2, 3.9, "ENG"))
.Add(New Siswa("1001", "Charles", 1, 2.6,
"BIO"))
.Add(New
Siswa("2205", "Sartono", 2, 3.1, "MTH"))
.Add(New Siswa("1961",
"David", 2, 2.2, "ENG"))
.Add(New Siswa("2210",
"Vivian", 3, 2.4, "BIO"))
.Add(New Siswa("1975",
"Rico", 3, 4.0, "ENG"))
End
With
Query LINQ berikut menyeleksi semua siswa
dari daftarSiswa dan mengurutkan
hasilnya secara menaik berdasarkan properti Siswa.Id:
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa
Order
by aSiswa.Id
Query berikut menyeleksi semua siswa dari
list dan mengurutkannya berdasarkan nama belakangnya:
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa
Order
by aSiswa.NamaBelakang
Anda dapat dengan mudah menugaskan keluaran
query kepada sebuah kontrol DataGridView,
seperti ditunjukkan pada Gambar 3.13. Anda hanya perlu mengkonversi keluaran
query menjadi sebuah List dan
menugaskannya kepada properti DataSource
dari grid:
dgvSiswa.DataSource
= query.ToList()
Jika Anda ingin menampilkan hanya beberapa
properti objek, Anda dapat mencantumkannya pada klausa Select, sebagai berikut:
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa.Jurusan, aSiswa.NamaBelakang
Order
By Jurusan
dgvSiswa.DataSource
= query.ToList()
Gambar 3.14 menampilkan sebuah query LINQ
pada sebuah kontrol DataGridView,
dimana pengurutannya dilakukan berdasarkan nama belakang.
Gambar 3.14 Menampilkan sebuah query LINQ pada sebuah
kontrol DataGridView, dimana
pengurutannya didasarkan pada properti NamaBelakang
Memfilter Baris
Operator Where
pada sebuah query LINQ menyediakan pemilteran, atau penyeleksian baris-baris
dari sumber data. Anda dapat mengkombinasikan properti-properti objek,
operator-operator perbandingan, pemanggilan-pemanggilan metode, dan
operator-operator gabungan.
Query berikut menyeleksi hanya siswa-siwa
dengan IPK lebih dari 3.0 dan mengurutkan hasilnya dengan tatanan menurun:
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa
Where
aSiswa.Ipk > 3.0
Order
By aSiswa.Ipk Descending
Query berikut menyeleksi hanya siswa-siswa
dengan IPK di bawah 3.2 dengan jurusan (BIO):
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa
Where
aSiswa.Ipk < 3.2 And aSiswa.Jurusan = “BIO”
Order
By aSiswa.Ipk Descending
Daripada menggunakan nilai konstanta untuk
perbandingan, Anda dapat menggunakan nilai pada kotak teks:
Dim
query = From aSiswa In daftarSiswa
Select
aSiswa
Where
aSiswa.Ipk < CDbl(teksIpk.Text) And aSiswa.Jurusan = teksJurusan.Text
Order By aSiswa.Ipk
Descending
Anda dapat menuliskan kode untuk menjelajah
daftarSiswa dan melakukan perbandingan-perbandingan. Tetapi LINQ melakukan
pekerjaan semacam itu dengan jauh lebih mudah. Pada Tutorial 3.4, Anda akan
melihat sejumlah cara dalam melakukan query terhadap sejumlah siswa dan
menghitung statistika pada list tersebut.
Tutorial 3.4: Melakukan query LINQ pada sebuah list
Pada tutorial
ini, Anda akan menciptakan sebuah aplikasi yang menggunakan query LINQ untuk
menampilkan, mengurutkan, memfilter, dan menghitung statistika pada sebuah list
yang memuat sejumlah siswa. Form startup memiliki sebuah menu dengan
seleksi-seleksi sehingga user dapat memilih pengurutan dan filter yang berbeda.
Hasil dari query akan ditampilkan pada sebuah kontrol DataGridView. Gambar 3.15, misalnya, menunjukkan keluaran dari
sebuah query LINQ yang mengurutkan siswa berdasarkan nama belakangnya dengan
tatanan menurun.
Form
Statistika pada Gambar 3.16 menampilkan statistika yang dihimpun dari list,
menggunakan query LINQ dan metode ekstensi. Ia menampilkan IPK rerata dari
semua siswa, rentang nilai IPK dari terkecil sampai terbesar, dan IPK rerata
dari jurusan yang dipilih oleh user dari sebuah kotak list. Kotak list itu
sendiri diisi dengan sebuah query LINQ.
Kelas Siswa yang digunakan pada kasus ini
adalah:
Public Class Siswa
Public Property Id As String
Public Property NamaBelakang As String
Public Property Status As Integer
'nilai: 1,2,3,4
Public Property Ipk As Double
'indeks prestasi kumulatif
Public Property Jurusan As String
'dan lainnya
Public Sub New(ByVal pId As String,
Optional ByVal pNamaBelakang As String = "",
Optional ByVal pStatus As Integer = 1,
Optional ByVal pIpk As Double = 0.0,
Optional ByVal pJurusan As String = "")
Id = pId
NamaBelakang = pNamaBelakang
Status = pStatus
Ipk = pIpk
Jurusan = pJurusan
End
Sub
End Class
Langkah 1: Buka projek dengan nama Daftar Siswa.
Langkah 2: Periksa item-item menu utama:
Urutkan dengan
ID,
menaik
Nama belakang, menurun
Pilih
Siswa dengan IPK > 3.0
Jurusan BIO dengan IPK < 3.2
Lihat
Statistika
Langkah 3: Buka jendela Code
dan periksa kode berikut:
Dim daftarSiswa As New List(Of Siswa)
Private Sub Form1_Load(…) Handles MyBase.Load
With
daftarSiswa
.Add(New Siswa("1241",
"Kristof", 1, 3.2, "BIO"))
.Add(New Siswa("1641",
"Bakri", 2, 3.9, "ENG"))
.Add(New Siswa("1001",
"Charles", 1, 2.6, "BIO"))
.Add(New Siswa("2205",
"Sartono", 2, 3.1, "MTH"))
.Add(New Siswa("1961",
"David", 2, 2.2, "ENG"))
.Add(New Siswa("2210",
"Vivian", 3, 2.4, "BIO"))
.Add(New Siswa("1975",
"Rico", 3, 4.0, "ENG"))
End
With
End Sub
Langkah 4: Periksa event handler Click untuk item menu Urutkan
Dengan | ID, menaik:
Private Sub mnuUrutkanID_Click(…) Handles
mnuUrutkanID.Click
'mengurutkan berdasarkan ID, secara menaik
Dim query = From aSiswa In daftarSiswa
Select aSiswa
Order By aSiswa.Id
'konversi
menjadi List(Of Siswa)
dgvSiswa.DataSource = query.ToList()
End Sub
Langkah 5: Periksa event handler Click untuk item menu Urutkan
Dengan | Nama Belakang, menurun:
Private Sub mnuUrutkanNamaBelakang_Click(…)
Handles mnuUrutkanNamaBelakang.Click
'mengurutkan berdasarkan nama belakang, secara
menurun
Dim query = From aSiswa In daftarSiswa
Select aSiswa
Order By aSiswa.NamaBelakang Descending
dgvSiswa.DataSource
= query.ToList()
End Sub
Langkah 6: Periksa event handler Click untuk item menu Pilih
| Siswa dengan IPK > 3.0:
Private Sub mnuPilihSiswa_Click(…) Handles
mnuPilihSiswa.Click
'siswa-siswa dengan IPK > 3.0
Dim query = From aSiswa In daftarSiswa
Select aSiswa
Where aSiswa.Ipk > 3.0
Order By aSiswa.Ipk Descending
dgvSiswa.DataSource = query.ToList()
End Sub
Langkah 7: Periksa event handler Click untuk item menu Pilih
| Jurusan BIO IPK < 3.2:
Private Sub mnuPilihJurusan_Click(…) Handles mnuPilihJurusan.Click
'jurusan BIO dengan IPK < 3.2
Dim query = From aSiswa In daftarSiswa
Select
aSiswa
Where aSiswa.Ipk < 3.2 And aSiswa.Jurusan =
"BIO"
Order By aSiswa.Ipk Descending
dgvSiswa.DataSource = query.ToList()
End Sub
Langkah 8: Periksa event handler Click untuk item menu Lihat |
Statistika:
Private Sub mnuLihatStatistika_Click(…)
Handles mnuLihatStatistika.Click
FormStatistika.DaftarSiswa = daftarSiswa
FormStatistika.ShowDialog()
End Sub
Langkah 9: Jalankan aplikasi dan verifikasi semua query
berdasarkan item-item menu. Kemudian hentikan aplikasi.
Form Statistika
Langkah 10: Buka jendela Code
untuk form Statistika. Ia memuat
sebuah properti yang memuat referensi ke list siswa yang telah diciptakan pada
kelas Form1:
Public Class FormStatistika
Public
Property DaftarSiswa As New List(Of Siswa)
Langkah 11: Periksa event handler Form_Load, yang menghitung IPK rerata. Karena Anda hanya
menginginkan nilai-nilai IPK, klausa Select
secara spesifik menyebutkan aSiswa.Ipk:
Private Sub FormStatistika_Load(…) Handles
MyBase.Load
'menghitung IPK rerata
Dim IPKQuery = From aSiswa In DaftarSiswa
Select aSiswa.Ipk
labelRerataIPK.Text =
IPKQuery.Average().ToString("n")
Metode
ekstensi dengan nama Average
menghasilkan nilai rerata dari semua nilai yang ditemukan oleh IPKQuery.
Pada event
handler yang sama, metode-metode ekstensi diterapkan pada objek IPKQuery untuk mendapatkan nilai
terkecil (Min) dan nilai terbesar (Max):
'menghitung IPK min dan maks
labelRentangIPK.Text =
IPKQuery.Min().ToString("n") &
"
- " & IPKQuery.Max().ToString("n")
Terakhir,
kode ini mengisi kontrol ListBox
dengan satu objek dari tiap jurusan. Ini dilakukan lebih dahulu dengan sebuah
query dengan nama (jurusan) dan
kemudian memanggil metode ekstensi dengan nama Distinct:
'mengisi kotak list dengan nama-nama jurusan
Dim jur = From aSiswa In DaftarSiswa
Select aSiswa.Jurusan
Order By Jurusan
kotakListJurusan.DataSource =
jur.Distinct().ToList()
Langkah 12: Periksa event handler SelectedIndexChanged untuk ListBox:
Private Sub
kotakListJurusan_SelectedIndexChanged(…)
Handles
kotakListJurusan.SelectedIndexChanged
Metode ini
menghitung IPK reraa dari siswa-siswa yang memiliki jurusan terseleksi, dalam
dua langkah: Pertama, ia menugaskan sebuah list siswa yang cocok dengan jurusan
terseleksi kepada jurusanQuery.
Dim jurusanQuery = From aSiswa In DaftarSiswa
Select aSiswa
Where aSiswa.Jurusan =
kotakListJurusan.SelectedItem.ToString
Kemudian, ia
menggunakan jurusanQuery sebagai
sumber untuk query kedua yang menyeleksi hanya properti Ipk dari tiap siswa.
Dim IPKQuery = From aSiswa In jurusanQuery
Select aSiswa.Ipk
Terakhir,
ketika IPKQuery ditugaskan kepada
kontrol Label, metode ekstensi
Average menghitung IPK rerata.
labelRerataIPKJurusan.Text =
IPKQuery.Average().ToString("n")
Melakukan Query Terhadap Dictionary
Anda dapat melakukan query LINQ pada sebuah Dictionary. Dengan menggunakan kelas Siswa yang sama seperti yang telah Anda
gunakan sebelumnya, kode berikut mengisi Dictionary
dengan entri-entri yang telah Anda gunakan untuk List:
Dim
kolSiswa As New Dictionary(Of Integer, Siswa)
With
kolSiswa
.Add(New Siswa("1241",
"Kristof", 1, 3.2, "BIO"))
.Add(New Siswa("1641",
"Bakri", 2, 3.9, "ENG"))
.Add(New Siswa("1001",
"Charles", 1, 2.6, "BIO"))
.Add(New Siswa("2205",
"Sartono", 2, 3.1, "MTH"))
.Add(New Siswa("1961",
"David", 2, 2.2, "ENG"))
.Add(New
Siswa("2210", "Vivian", 3, 2.4, "BIO"))
.Add(New Siswa("1975",
"Rico", 3, 4.0, "ENG"))
End
With
Penulisan query LINQ untuk memproses Dictionary sedikit berbeda dari
penulisan query untuk List. Setiap
entri di dalam sebuah Dictionary
adalah bertipe KeyValuePair, yang
memiliki dua properti dengan nama Key
dan Value. Operator Select di dalam sebuah query LINQ perlu
mereferensi properti Value dari
pasangan tersebut.
Query beriktu menyeleksi semua siswa dari Dictionary dan mengurutkannya
berdasarkan nomor ID:
Dim
query = From aSepasang In kolSiswa
Select
aSepasang.Value
Order
By Value.Id
Karena ekspresi aSepasang.Value menghasilkan sebuah objek Siswa, operator Order By perlu menggunakan Value.Id untuk mengindikasikan properti
Siswa spesifik dalam mengurutkan
hasil query.
Cara alternatif adalah dengan menjalankan
query LINQ pada koleksi Values dari Dictionary, yang ia sendiri merupakan
sebuah List. Contohnya diberikan
berikut:
Dim
query = From aSiswa In kolSiswa.Values
Select
aSiswa
Order By aSiswa.Id
Kelas yang Memuat List-List
Salah satu fitur tangguh dari LINQ adalah
kemampuannya untuk mengakses dan melakukan pencarian pada sebuah List yang bisa saja berada di dalam
kelas lain. Dimisalkan bahwa sebuah program mendeklarasikan sebuah list yang
memuat objek-objek Akun, sebagai
berikut:
Dim akunList As List(Of Akun)
Setiap Akun memuat sebuah ID dan sebuah list
yang memuat sejumlah saham:
Class Akun
Public
Property ID As Integer
Public
Property SahamList As List(Of Saham)
End Class
Sebuah objek Saham memuat sebuah Penjelasan
dan sebuah harga:
Class
Saham
Public Property Penjelasan As String
Public Property Harga As Double
End
Class
Pertama, Anda dapat menuliskan sebuah query
LINQ yang menyeleksi satu akun yang sesuai/cocok dengan nomor ID yang disimpan
di dalam sebuah variabel dengan nama IDAkunCari:
Dim querySatu = From ak In akunList
Where ak.ID = IDAkunCari
Select ak
Setelah querySatu
memuat objek Akun terseleksi, Anda
dapat memanggil metode ekstensi ElementAt
untuk menghasilkan sebuah referensi yang menunjuk ke objek Akun dan membaca list yang memuat saham-saham:
Dim
sahamList As List(Of Saham) = querySatu.ElementAt(0).SahamList
Banyak programer yang menghemat kode dengan
menggabungkan hal ini menjadi satu query. Perhatikan bagaimana kurung harus
mengapit list pertama sebelum memanggil metode ElementAt:
sahamList = (From ak In akunList
Where ak.ID = IDAkunCari
Select ak).ElementAt(0).SahamList
No comments:
Post a Comment