Pengarang AllenB.Downey
Copyright2003AllenDowney. Permissionisgrantedtocopy,distribute,and/ormodifythisdocumentunder thetermsoftheGNUFreeDocumentationLicense,Version1.1oranylaterver sionpublishedbytheFreeSoftwareFoundation;withInvariantSectionsbeing Preface,withnoFrontCoverTexts,andwithnoBackCoverTexts.Acopy ofthelicenseisincludedintheappendixentitledGNUFreeDocumentation License. TheGNUFreeDocumentationLicenseisavailablefromwww.gnu.orgorby writingtotheFreeSoftwareFoundation,Inc.,59TemplePlace,Suite330, Boston,MA021111307,USA.
Copyright (c)
Jawaban Latihan 2006 oleh Wim Permana, Muhammad Fuad Dwi Rizki, dan Agus Juliardi. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNUFree Documentation License".
DaftarIsi
1. AlurProgram..............................................................................................................14 1.1ApaituBahasaPemrograman?.............................................................................14 1.2Apaituprogram?.................................................................................................17 1.4BahasaFormaldanNatural...................................................................................21 1.5ProgramPertama...................................................................................................24 1.6DaftarKata............................................................................................................27 1.7.Latihan.................................................................................................................28 2. VariabeldanTipenya..................................................................................................31 2.1Mencetaklebihbanyak.........................................................................................31 2.2Variabel.................................................................................................................33 2.3Assignment...........................................................................................................34 2.4MencetakVariabel................................................................................................36 2.5Keywords..............................................................................................................38 2.6Operator................................................................................................................39 2.7Operasi..................................................................................................................41 2.8OperatorpadaString.............................................................................................42 2.9Komposisi.............................................................................................................43 2.10Daftarkata...........................................................................................................44 2.11Latihanlatihan....................................................................................................46 3. Method........................................................................................................................49 3.1Floatingpoint........................................................................................................49 3.2Mengkonversidoublekeint..................................................................................51 3.3MethodMatematika..............................................................................................52 3.4Composition..........................................................................................................54
3.5Menambahkanmetodebaru..................................................................................55 3.6Classdanmethod..................................................................................................59 3.7Programdenganbanyakmethod...........................................................................61 3.8Parameterdanargumen........................................................................................62 3.9Stackdiagram.......................................................................................................65 3.10MetodeDenganBanyakParameter....................................................................66 3.11Methoddanhasilnya...........................................................................................67 3.12Daftarkata...........................................................................................................68 3.13Latihan................................................................................................................69 4. Kondisionaldanrekursi..............................................................................................74 4.1Operatormodulus.................................................................................................74 4.2Percabangan..........................................................................................................74 4.3EksekusiAlternatif...............................................................................................76 4.4PercabanganBerantai...........................................................................................77 4.5PercabanganBersarang.........................................................................................78 4.6Thereturnstatement.............................................................................................79 4.7KonversiTipe........................................................................................................80 4.8Recursion..............................................................................................................81 4.9DiagramStackUntukMetodeRekursif................................................................84 4.10KonvensidanDivineLaw...................................................................................85 4.11DaftarKata.........................................................................................................86 4.12Latihan................................................................................................................87 5. Fruitfulmethods..........................................................................................................93 5.1NilaiKembalian....................................................................................................93 5.2PengembanganProgram.......................................................................................96 5.3Komposisi...........................................................................................................100 4
5.4Overloading........................................................................................................101 5.5EkspresiBoolean................................................................................................103 5.6OperatorLogika.................................................................................................104 5.7MetodeBoolean..................................................................................................105 5.8LagitentangRekursi..........................................................................................106 5.9Leapoffaith........................................................................................................109 5.10SatuContohLagi..............................................................................................111 5.11DaftarKata........................................................................................................112 5.12Latihan.............................................................................................................113 6. Iterasi.........................................................................................................................121 6.1MultipleAssignment...........................................................................................121 6.2Iterasi..................................................................................................................123 6.3PernyataanWhile...............................................................................................123 6.4Tabel...................................................................................................................126 6.5TabelDuaDimensi.............................................................................................129 6.6EnkapsulasidanGeneralisasi..............................................................................131 6.7Metode................................................................................................................133 6.8Enkapsulasi....sekalilagi!..................................................................................133 6.9VariabelLokal....................................................................................................134 6.10Generalisasi.Sekalilagidengannya................................................................135 6.11DaftarKataKata...............................................................................................139 6.12Latihan..............................................................................................................140 7. String.........................................................................................................................145 7.1Memanggilmetodedalamobjek.........................................................................145 7.2Length.................................................................................................................147 7.3Traversal.............................................................................................................148 5
7.4RunTimeerrors.................................................................................................149 7.5MembacaDokumentasi......................................................................................149 7.6MetodeindexOf..................................................................................................150 7.7LoopingdanCounting........................................................................................153 7.8OperatorIncrementdanDecrement....................................................................154 7.9StringsareImmutable.........................................................................................155 7.10StringsareIncomparable..................................................................................156 7.11DaftarKataKata...............................................................................................158 7.12Latihan..............................................................................................................159 8. InterestingObjects....................................................................................................168 8.1Apanyayangmenarik?.......................................................................................168 8.2Paketpaket..........................................................................................................168 8.3ObjekTitik(Point)..............................................................................................169 8.4VariabelInstan...................................................................................................170 8.5ObjekSebagaiParameter....................................................................................171 8.6Rectangle.............................................................................................................172 8.7Objeksebagaitipekembalian(ReturnType).....................................................173 8.8Objekdapatdiubahubah(Mutable)...................................................................173 8.9Aliasing...............................................................................................................175 8.10Null...................................................................................................................176 8.11GarbageCollection...........................................................................................177 8.12ObjekdanPrimitif.............................................................................................178 8.13DaftarKataKata...............................................................................................180 8.14Latihan..............................................................................................................181 9. MembuatObjekAndaSendiri..................................................................................188 9.1Definisidefinisikelasdantipetipeobjek..........................................................188 6
9.2Time...................................................................................................................189 9.4KonstruktorLagi.................................................................................................192 9.5MembuatSebuahObjekyangBaru....................................................................193 9.6MencetakSebuahObjek.....................................................................................195 9.7OperasiPadaObjek.............................................................................................196 9.8Fungsifungsimurni............................................................................................197 9.9Modifier..............................................................................................................200 9.10FillinMethods..................................................................................................202 9.11Manayangterbaik?...........................................................................................203 9.12Pengembangansecarabertahapvsperencanaan...............................................204 9.13Generalisasi.......................................................................................................206 9.14Algoritma..........................................................................................................207 9.15DaftarKataKata...............................................................................................208 9.16Latihan.............................................................................................................209 10.Array.........................................................................................................................215 10.1MengaksesElemen...........................................................................................216 10.2MenyalinArray.................................................................................................217 10.3BentukPerulanganfor.....................................................................................218 10.4ArraydanObjek................................................................................................220 10.5PanjangArray...................................................................................................220 10.6AngkaAngkaAcak(Random)........................................................................221 10.7ArraydariAngkaangkaRandom(Acak)........................................................223 10.8Pencacahan........................................................................................................225 10.9Histogram..........................................................................................................227 10.10SolusiSinglePass...........................................................................................228 10.11DaftarKataKata.............................................................................................229 7
10.12Latihan............................................................................................................230 11.ArrayberisiObjek....................................................................................................238 11.1Komposisi.........................................................................................................238 11.2ObjekCard........................................................................................................238 11.3MetodeprintCard..............................................................................................241 11.4MetodesameCard.............................................................................................243 11.5MetodecompareCard........................................................................................245 11.6ArrayberisiCard..............................................................................................248 11.7MetodeprintDeck.............................................................................................250 11.8Searching..........................................................................................................251 11.9Tumpukandansubtumpukan............................................................................257 11.10DaftarKataKata.............................................................................................258 11.11Latihan............................................................................................................259 12.ObjekberisiArray....................................................................................................261 12.1KelasDeck........................................................................................................261 12.2Shuffling...........................................................................................................264 12.3Pengurutan(Sorting).........................................................................................265 12.4Subtumpukan(Subdecks).................................................................................266 12.5PengacakandanPembagianKartu(ShufflingandDealing).............................268 12.6Mergesort..........................................................................................................270 12.7DaftarKataKata...............................................................................................274 12.8Latihan..............................................................................................................274 13.PemrogramanBerorientasiObjek............................................................................280 13.1BahasaPemrogramandanTekniktekniknya...................................................280 12.3MetodeObjekdanMetodeKelas......................................................................281 13.3ObjekTerkini....................................................................................................281 8
13.4BilanganKompleks...........................................................................................282 13.5FungsifungsidalamBilanganKompleks.........................................................283 13.6FungsifungsilainnyadalamBilanganKompleks............................................285 13.7Modifier............................................................................................................286 13.8MetodetoString................................................................................................287 13.9Metodeequals...................................................................................................288 13.10MemanggilSatuMetodeObjekdariMetodeObjekLain..............................289 13.11KeganjilandanError.......................................................................................290 13.12Inheritance.......................................................................................................291 13.13Lingkaranyangbisadigambar.......................................................................292 13.14HierarkiKelas.................................................................................................293 13.15RancanganBerorientasiObjek.......................................................................294 13.16DaftarKataKata.............................................................................................295 13.17Latihan............................................................................................................296 14.LinkedList................................................................................................................298 14.1AcuanacuandalamObjek................................................................................298 14.2KelasNode........................................................................................................298 14.3ListsebagaiCollection......................................................................................301 14.4ListdanRekursi................................................................................................302 14.5InfiniteList........................................................................................................304 14.6TeoremaAmbiguitasFundamental...................................................................305 14.7MetodeObjekUntukNodeNode.....................................................................306 14.8MemodifikasiList.............................................................................................307 14.9WrappersdanHelpers.......................................................................................308 14.10KelasintList....................................................................................................310 14.11Invariants.........................................................................................................312 9
14.12DaftarKataKata.............................................................................................313 14.13Latihan............................................................................................................313 15.Stacks........................................................................................................................316 15.1TipeDataAbstrak............................................................................................316 15.2TheStackADT.................................................................................................317 15.3ObjekStackdalamJava....................................................................................318 15.4KelasPembungkus............................................................................................320 15.5MembuatKelasPembungkus............................................................................321 15.6MembuatKelasPembungkusLagi...................................................................321 15.7MengeluarkanNilaiNilai.................................................................................322 15.8MetodeMetodeBermanfaatdalamKelasPembungkus...................................323 15.9EkspresiPostfix................................................................................................324 15.10Parsing............................................................................................................325 15.11MengimplementasikanADT...........................................................................327 15.12ImplementasiArrayuntukStackADT...........................................................327 15.13MengubahUkuranArray................................................................................329 15.14DaftarKataKata.............................................................................................332 15.15Latihan............................................................................................................333 16.AntriandanAntrianPrioritas...................................................................................337 16.1ADTAntrian.....................................................................................................338 16.2Veneer...............................................................................................................340 16.3LinkedQueue....................................................................................................343 16.4CircularBuffer..................................................................................................345 16.5PriorityQueue...................................................................................................351 16.6Metaclass...........................................................................................................352 16.7ImplementasiArrayuntukAntrianPrioritas....................................................353 10
16.8KlienAntrianPrioritas......................................................................................355 16.9KelasGolfer......................................................................................................357 16.10DaftarKataKata.............................................................................................360 16.11Latihan............................................................................................................361 17.Pohon(Trees)...........................................................................................................364 17.1SimpulPohon....................................................................................................364 17.2MembuatPohon................................................................................................365 17.3MenelusuriPohon.............................................................................................366 17.4PohonEkspresi.................................................................................................367 17.5Penelusuran.......................................................................................................368 17.6Enkapsulasi.......................................................................................................370 17.7Mendefinisikanmetaclass.................................................................................372 17.8MengimplementasikanMetaclass.....................................................................373 17.9KelasVector......................................................................................................374 17.10KelasIterator...................................................................................................377 17.11DaftarKataKata.............................................................................................378 17.12Latihan............................................................................................................380 18.Heap..........................................................................................................................384 18.1ImplementasiPohonmenggunakanArray........................................................384 8.2AnalisisKinerja.................................................................................................389 18.3AnalisisMergeSort..........................................................................................392 18.4Overhead...........................................................................................................394 18.5ImplementasiPriorityQueue.............................................................................395 18.6DefinisiHeap...................................................................................................397 18.7Penghapusanpadaheap....................................................................................398 18.8PenambahanHeap............................................................................................400 11
18.9KinerjaHeap....................................................................................................401 18.10Heapsort..........................................................................................................403 18.11DaftarKataKata.............................................................................................404 18.12Latihan............................................................................................................405 19.Maps.........................................................................................................................407 19.1Array,Vector,Map...........................................................................................407 19.2MapADT..........................................................................................................408 19.3HashMapbuiltin..............................................................................................408 19.4ImplementasiDenganVector...........................................................................414 19.5KelasAbstrakList.............................................................................................422 19.6ImplementasidenganHashMap........................................................................423 19.7FungsiHash......................................................................................................424 19.8MengubahUkuranHashMap...........................................................................427 19.9Kinerjadaripengubahanukuran.......................................................................428 19.10DaftarKata......................................................................................................429 19.11Latihan............................................................................................................430 20.KodeHuffman..........................................................................................................434 20.1Variabellengthcodes.......................................................................................434 20.2Tabelfrekuensi................................................................................................435 20.3PohonHuffman.................................................................................................437 20.4Metodesuper.....................................................................................................440 20.5PemecahanKode...............................................................................................443 20.6Pengkodean.......................................................................................................444 20.7DaftarKata........................................................................................................445 21.LampiranForeachdanGenerik................................................................................446 Generik......................................................................................................................446 12
Foreach......................................................................................................................448 DaftarKata...............................................................................................................451 22.JawabanLatihan.......................................................................................................452 Bab2.........................................................................................................................452 Bab3.........................................................................................................................453 Bab4.........................................................................................................................456 Bab6.........................................................................................................................457 Bab7.........................................................................................................................465 Bab8.........................................................................................................................471 Bab9.........................................................................................................................473 Bab10.......................................................................................................................478 Bab11.......................................................................................................................488 Bab12.......................................................................................................................492 Bab13.......................................................................................................................504 Bab14......................................................................................................................507 Bab15.......................................................................................................................520 Bab16.......................................................................................................................537 Bab17.......................................................................................................................546 Bab18.......................................................................................................................556 Bab19.......................................................................................................................566 BAB20.....................................................................................................................588 23.History.....................................................................................................................606 24.GNUFreeDocumentationLicense..........................................................................606
13
BAB1 AlurProgram
Tujuandaribukuinidankelasiniadalahuntukmengajarkanandauntukberfikirseperti ahli komputer. Saya menyukai cara berfikir ahli komputer karena mereka menggabungkanbeberapafiturmatematika,engineering,danilmualam.Sepertiahli matematika, ilmu komputer menggunakan bahasa formal untuk mengutarakan ide (secara spesifik komputasi). Seperti seorang engineer, komputer mendesain sesuatu, mengumpulkankomponenkedalamsistemdanmengevaluasialternatifantarpertukaran data.Sepertiseorangilmuwan,komputermenelitisifatkompleksitassistem,hipotesa formdanprediksites.
Salah satu dari kemampuan penting dari komputer adalah pemecahan masalah (ProblemSolving).Denganpengertiankemampuanuntukmemformulasikanmasalah, berfikir secara kreatif pemecahannya dan mengekspresikan solusi secara jelas dan sayarat. Dengan demikian, proses dari pembelajaran ke program merupakan kesempatan sempurna untuk mempraktekkan kemampuan pemecahan masalah. Oleh karenaitubabinidinamakanAlurProgram.
1.1ApaituBahasaPemrograman?
BahasaPemrogramanyangakanAndapelajariadalahJava,yangrelatifmasihbaru
14
(Sun merilis versi pertama pada bulan mei 1995). Java merupakan contoh bahasa tingkattinggi;bahasatingkattinggilainnyayangmungkinpernahAndadengaradalah pascal,C,C++,danFORTRAN.
SepertiyangAndadugaselainBahasaTingkatTinggiadajugaBahasaTingkatRendah. Kadangkadangdikenaljugadenganbahasamesinataubahasaasembly.Dengankata lain komputer hanya dapat mengeksekusi program dalam bahasa tingkat rendah. Sehingga program yang ditulis menggunakan bahasa tingkat harus diterjemahkan terlebihdahulusebelumdapatdiJalankan.Terjemahaniniakanmemakanwaktudan itulahsedikitkekurangandaribahasatingkattinggi.
Akan tetapi keuntungannya sangat banyak, pertama, sangatlah mudah membuat programdenganbahasatingkattinggi,mudahdalamartiprogramdapatdibuatdalam waktu singkat, cepatdanmudah dibacadanmudahuntuk dikoreksi. Kedua,bahasa tingkattinggibersifatportable,yangberartibahwabahasatingkattinggidapatberjalan diberbagaikomputeryangberbeda dengansedikitataupuntanpamodifikasi.Bahasa tingkatrendahhanyadapatberjalanpadasatumacamkomputersajadanharusditulis ulangjikadijalankanpadakomputerlainnya.
Dengan beberapa keuntungan ini, hampir semua program yang ditulis dengan menggunakan bahasa tingkat tinggi. Bahasa tingkat rendah hanya digunakan untuk aplikasitertentusaja.Adaduacaradalammenterjemahkanprogram; diterjemahkan (intrepeter) atau di compile. Penterjemah (intrepeter) adalah sebuah program yang membaca program tingkat tinggi dan menerjemahkan perintahnya. Sebagai efeknya, programditerjemahkanperbaris.Secaraberurutanmembacabarisdanmelaksanakan perintahnya. 15
Compiler adalah sebuah program yang membaca suatu bahasa tingkat tinggi dan menterjemahkan semua sekaligus sebelum mengeksekusi perintah. Biasanya Anda sering membuatprogramsecaraterpisahlalumengeksekusikodenyadiakhir.Dalam kasus ini program tingkat tinggi dinamakan source code dan terjemahan program dinamakanobjectcodeatauexecutable. Sebagai contoh sekiranya Anda menulis program dalam bahasa C. Anda mungkin menggunakantekseditoruntukmenulisprogram(tekseditoradalaheditorsederhana). Ketikaprogramselesai,Andamungkinmenyimpannyadalamsebuahfiledengannama program.c,dimanaprogramadalahnamafile.Danakhiran.cadalahconvensiyang menandaikodeprogramdalambahasaC. Lalu, berdasarkan programming environment yang Anda sukai, Anda bisa meninggalkan text editor dan menjalankan compilernya. Compiler akan membaca sourcecodeanda,menterjemahkannya,danmembuatfilebaruyangbernamaprogram.o yangberisikodeobjekatauprogram.exeyangexecutable.
16
PadabahasaJavatidaksepertibiasakarenalangsungdikompilasidandiinterpreted. SebagaigantiterjemahanbahasaJavakebahasamesin,JavaCompilermengenerate javabytecode.Bytecodesangatmudahdiinterpretasikansepertibahasatingkattinggi. Seperti itu, dimungkinkan untuk mengkompile program java pada satu mesin, lalu mentransferbytecodekemesinlaindenganjaringan.lalumenginterpretasikanbyte code ke mesinlainnya.KemampuaniniadalahsalahsatukeunggulanJavadiantara banyakkeunggulanlainnyasebagaibahasatingkattinggi.
Walaupunprosesinitampakrumit,padakebanyakanlingkunganpemrograman(kadang disebut development environment), langkah ini langsung secara otomatis. Biasanya Andahanyamenulisprogramdanmenekantombolcompileuntukmengcompiledan untukmenjalankannya.Disisilainhalinibergunauntukmengetahuilangkahnyadan apa yang terjadi pada layar. Sehingga jika terjadi kesalahan Anda dapat langsung memperbaikinya.
1.2Apaituprogram?
Program adalah urutan dari perintahperintah tertentu untuk melaksanakan proses komputasi.Komputasidapatberupabeberapaperhitunganmatematika,sepertihalnya menyelesaikansuatusistempersamaanuntukmenemukanakarakarpolinomial.Akan 17
tetapijugabisaberupasebuahsimbolkomputasisepertisearching,danreplacingteks padasebuahdokumenataucaralain(mengcompilesebuahprogram).
Perintahyangkitasebutsebagaisuatupernyataan,kelihatanberbedapadasetiapbahasa pemrogramanyangberbedatetapiterdapatbeberapaoperasidasaryangkebanyakan bahasamenyediakan: Input :memasukkan data dari keyboard, atau sebuah file, atau beberapa perangkatlain. Output :menampilkandatadarilayardanmembuatsebuahfileatauperangkat lain. Math :menyelesaikan operasi dasar matematika seperti penambahan, dan perkalian. Testing :mencek kondisi tertentu dan mengeksekusi urutan dari pernyataan yangsesuai. Repetition :melakukansuatuaksisecaraberulangbiasanyadenganbeberapavariasi.
Semuahaldiatassangatlahbaik.SetiapprogramyangpernahAndagunakan,tak masalah itu rumit, terdiri dari pernyataanpernyataan yang melaksanakan beberapa operasi.Lalusatucarauntukmenggambarkanpemrogramanyaitusebuahprosesdari Taskyangbesardankompleksmenjadisubtaskyangkecilbahkansampaipadasubtask yangcukupsederhanayangdilakukankandengansatuoperasioperasidasar.
Compilertidakmemperbolehkansatukesalahan.Jikaadasatukesalahanpadaprogram Anda,compilerakanmenampilkanpesankesalahandan lalukeluar.SehinggaAnda tidakbisamenjalankanprogramAnda. Untukmempersulitpersoalan,adabeberapaperaturansyntaxpadaJavayangdalam bahasainggris,danpesankesalahanyangandaterimadaricompilerseringtidakbanyak membantu.Selamabeberapaminggupertamapembuatanprogramanda,kemungkinan Anda akan menghabiskan waktu untuk mencari kesalahan syntax. Semakin anda mendapatkan pengalaman maka anda semakin sedikit melakukan kesalahan dan semakincepatmenemukanerror.
1.3.2RUNTIMEERROR TipekeduadarierroradalahRuntimeerror.Disebutdemikiankarenaerroryangterjadi tidak muncul sampai program dijalankan. Pada Java runtime errror terjadi ketika interperetermenjalankanbytecodedanterjadisuatukesalahan.
Untungnya, Java cenderung merupakan bahasa yang aman. Yang berarti runtime errornyajarang,terutamapadaprogramsingkatyangsederhanayangakankitatulis untukbeberapamingguselanjutnyakedepan.
Kemudiandalamsemesternanti,Andakemungkinanakanmelihatlebihjelastentang runtimeerror.Terutamketikakitamembicarakantentangobjekdanreference.(Bab8).
prosesDebugging.
Masalahnyaprogramyangandatulisbukanlahprogramyangandainginkan.Artinya programnya(semantiknya)salah.Mengindentifikasilogicalerrorsangatsulit.Karena itu mengharuskan anda untuk kembali melihat output program dan mencoba untuk memperbaikiapayangtelahdilakukan.
1.3.4Experimentaldebugging Salah satu dari kemampuan penting yang akan Anda dapatkan dikelas ini adalah debugging.Walaupunitudapatmenimbulkanfrustasi,debuggingadalahsalahsatudari halyangberalasan,menantangdanmenarikdalamsebuahpemrograman.
Debuggingjugasepertiilmupercobaan.SesekaliAndamemilikiideapayangakan salah,Andamemperbaikiprogramdanmencobanyalagi.JikahipotesisAndabenar,
20
laluAndadapatmemprediksihasildarimodifikasi,laluAndamengambillangkahyang terdekatuntukmengerjakanprogram.JikahipotesisAndasalahAndaharusmengulang lagi membuat program yang baru. Sherlock Holmes mengatakan: jika Anda telah mengeliminasi ketidakmungkinan, maka apa saja yang tersisa haruslah benar (dari ConanDoyle'sTheSignofFour).
Kebanyakan orang mengatakan, programming dan debugging adalah sama. Bahwa programmingmerupakansuatuprosesyangberangsurangsurdaridebuggingsebuah program sampai akhirnya menjadi program yang diinginkan. Artinya bahwa Anda memulai program kerja dengan melakukan sesuatu, membuat modifikasi kecil lalu melakukandebuggingsehinggaAndaselalumemilikiprogramkerja.
DibabselanjutnyaSayaakanlebihmenyarankanuntukmempelajaritentangdebugging danlatihanprogramlainnya.
1.4BahasaFormaldanNatural
Bahasa Natural adalah bahasa yang diucapkan oleh orang, seperti bahasa Inggris, Spanyol, dan perancis. Bahasa Natural tidak dibuat oleh manusia (walaupun orang mencobamengatakandemikian),bahasanaturalterciptasecaraalami.
21
Bahasa Formaladalahbahasayangdidesainoranguntukaplikasitertentu.Sebagai contoh, notasi matematika menggunakan bahasa formal yang umumnya baik untuk menjelaskan hubungan antara angka dan simbol. Ahli kimia menggunakan bahasa formaluntukmerepresentasikanstrukturmolekulkimiadanbanyaklagi.
Bahasapemrogramanadalahbahasaformalyangdidesainuntuk mengekpresikansuatukomputasi
Seperti yang disebutkan diawal, bahasa formal mempunyai aturan yang tegas pada syntax.Sebagaicontoh,3+3=6adalahpernyataanmatematikayangsyntaxnyabenar. Tetapi3=6$bukan.JugaH2Oadalahsyntaxyangbenarsecarakimia.Tapi2Zztidak benar.
Peranansyntaxadadua,sebagaitandadanstruktur. Tandaadalahelemendasardari suatu bahasa. Seperti kata dan angka dan unsurunsur kimia. Satu masalah dengan 3=+6$bahwa$bukanlahtandayangbenarsecaramatematika(sejauhyangsayatahu).
2ZzsalahkarenatidakadaunsurdengantandaZz.
Yang kedua jenis aturan sintaksis menyinggung kepada struktur suatu statemen, maksudnyasuatutandadiatur.Statemen3=+6$darisudutbangunannyatidakbenar, sebabAndatidakbisamempunyaisuatutandapertambahansetelahsuatutandasama dengan.Dengancarayangsama,rumusanmolekularharusmempunyaitulisandibawah barissetelahnamaunsur,yangsebelumnyatidak.
KetikaAndamembacasuatukalimatdidalamBahasaInggrisatausuatustatemendi dalamsuatubahasaformal,Andaharusmenggambarkankeluarapastrukturkalimat 22
tersebut(walaupundidalamsuatubahasaalamiyangAndalakukaninitanpadisadari). Prosesinidisebutparsing.
Sebagaicontoh,ketikaAndamendengarkalimat,Sepatulainjatuh,"Andamemahami bahwasepatulain"adalahsubjekdanjatuh"adalahkatakerja. Sekaliandasudah menguraikan suatu kalimat, anda dapat menggambarkan apa maknanya, itu adalah maknasemantikdarisebuahkalimat.AsumsikanbahwaAndamengetahuisepatuapa itu,danapamaknajatuh,andaakanmemahamiimplikasiyangumumdarikalimatini.
Bagaimanapunbahasaalamidanformalmempunyaibanyakfiturpadatanda,struktur, sintaksisdansemantikadabanyakperbedaan.
Ambiguitas: Bahasa alami adalah penuh dengan kerancuan, yang mana orang berhadapandengandenganpenggunaantandadaninformasilainnya.Bahasa formal dirancangdenganhampiratausamasekalitidakbersifatambigu,yangberartibahwa semuastatemenpersismempunyaisatuartidenganmengabaikankonteks. Redudancy:Dalamrangkamengejarkerancuandanmengurangisalahpaham,bahasa alamibanyakmengandungredudancy.Sebagaihasilnya,bahasaalamiseringbertele tele.Bahasaformaladalahlebihsedikitlebihringkasdantidakberlebihlebihan.
Harfiah:Bahasaalamipenuhdenganidiomdankiasan.JikaSayamengatakan,sepatu lain jatuh," kemungkinan tidak ada sepatu dan tidak ada apapun yang jatuh.Bahasa formalpersissepertiapayangdikatakan.Orangberbicaratentangsuatubahasaalami sering mempunyai kesulitan pada waktu menyesuaikan ke bahasa formal. Dalam beberapahalperbedaanantarabahasaformaldanbahasaalamisepertiperbedaanantara
23
sebuahpuisidanprosa,tetapi:
Prosa:Arti katakata secara harfiah lebih penting dan pemberdayaan struktur lebih berarti.Prosajadilahlebihbisadianalisadibandingpuisi,namunseringrancu.
Program: Arti dari suatu program komputer tidak ambigu dan jelas, dan dapat dipahamiseluruhnyaolehanalisatandadanstruktur.
Di sini adalah beberapa usul untuk membaca program ( dan bahasa formal lain). Pertama,ingatbahwabahasaformaljauhlebihtebal/padatdibanding bahasaalami, sehinggamemakanwaktulebihuntukmemahaminya.Strukturnyajugasangatpenting, jadibukanlahgagasanyangbaikjikamembacadariatassampaikebawah,darikirike kanan. Sebagai gantinya belajar menguraikan kalimat program dapat mengidentifikasikan tanda dan menginterpretasikan struktur. Yang akhirnya, ingat bahwa perihal detil. HalHal kecil seperti mengeja kesalahan dan tanda baca tidak baik,dapatAndahindaridaribahasaalami,dapatmembuatsuatuperbedaanbesardi dalamsuatubahasaformal.
1.5ProgramPertama
Biasanya program pertama orangorang pada suatu bahasa baru dinamakan dengan HelloWorld."sebabsemuanyaitumenampilkanHelloworld"DidalambahasaJava, programnyaseperti: 24
classHello{
Sebagian orang menilai mutu suatu bahasa program terlihat dari kesederhanaannya HelloWorld"Program.Denganstandardini,bahasaJavatidakmelakukanseluruhnya denganbaik.Bahkanprogramyangpalingsederhanaberisisejumlahcodeyangsulit dijelaskanpadaparaprogrammerpemula.Marikitaabaikansemuanyaterlebihdahulu. Sekarang,sayaakanmenjelaskanbeberapa.
Semuaprogramterdiridaridefinisikelas,yangmempunyaiformat:
DisiniCLASSNAMEmenunjukkanbahwasuatunamadapatandatentukansendiri. NamakelaspadacontohiniadalahHello. 25
Tidakadabatasjumlahdaristatemenyangterdapatdidalammain,padacontohhanya berisi satu. Ini merupakan suatu statemen cetakan, maksudnya bahwa itu mencetak suatupesanpadalayar,dengankatalainberartimengirimkansesuatukeprinter.Dalam bukuinisayatidakakanbanyakmengatakantentangmengirimkanberbagaihalkepada printer.Tetapiakanmencetaknyapadalayar.
Statemen yang mencetak berbagai hal pada layar adalah System.Out.Println, Dan diantaratandakurungadalahhalyangakandicetak.Padabagianakhirstatemenada suatutitikkoma(;),yangmanadiperlukanpadaujungtiaptiapstatemen.
Ada beberapa lain yang anda perlu perhatikan tentang sintaksis dari program ini. Pertama,bahasaJavamenggunakankurungkurawal({dan})untukmengolongkan sesuatusecarabersama.Kurungkurawalyangpalingjauh(baris1dan8)berisidefinisi kelas,danbagiandalamberisidefinisidarimain.
Perhatikanbaris3mulaidengan//.Inimenandakanpadabarisiniberisikomentarpada teks Bahasa Inggris anda dapat menaruhnya pada pertengahan program, biasanya menjelaskanapayangprogramkerjakan.Ketikacompilermelihattanda//,makaakan mengabaikansegalanyadarisanasampaiakhirbaris.
26
1.6DaftarKata
Problemsolving: Proses merumuskan suatu masalah,menemukan suatu solusi, dan menyatakansolusiitu. Highlevellanguage:SuatubahasaprogramsepertibahasaJavayangdirancanguntuk memudahkanmanusiauntukmembacadanmenulis. Lowlevel language: Suatu bahasa program yang dirancang untuk memudahkan komputer untuk melaksanakannya. Juga disebut bahasa mesin" atau bahasa assembly. Bahasaformal:Bahasayangsudahdirancanguntukmempresentasikansuatugagasan matematikaatauprogramkomputer.Semuabahasaprogramadalahbahasaformal. Bahasaalami:Bahasaorangyangmanapunitusudahterbentuksecraalami. Portabilitas: Suatu properti dari suatu program yang dapat berjalan lebih dari satu macamkomputer. Interpreted:Untukmengeksekusisuatuprogramdidalamsuatuhighlevellanguage menterjemahkannyaperbarispadawaktuyangsama. Compile:Untukmenterjemahkansuatuprogramdidalamsuatuhighlevellanguageke dalamsuatulowlevellanguage,untukkemudiandieksekusi. Source program: Suatu program di dalam suatu highlevel language sebelum di compile. ObjectCode:Keluarancompiler,setelahmenterjemahkanprogramitu. Executable:Namalainuntukobjectcodeyangsiapuntukdieksekusi. ByteCode:SemacamobjectcodekhususdigunakanuntukProgramJava.ByteCode serupa dengan suatu lowlevel language, tetapi portable sama seperti highlevel language.
27
Statement:Bagiandarisuatuprogramyangmerupakansesuatuyangakandikanketika programberjalan.Suatucetakanstatemenmenyebabkankeluaranpadalayar. Comment:Bagiandarisuatuprogramyangberisiinformasitentangprogram,tetapiitu tidakmempunyaiefekketikaprogramberjalan. Algorithm:Suatuprosesumumuntukmemecahkansuatukategoripermasalahan. Bug:Suatukesalahandidalamsuatuprogram. Syntax:Struktursuatuprogram. Semantic:Artidarisuatuprogram. Parse:Untukmengujidanmenganalisissuatustruktursyntaxsebuahprogram. Syntax error:Suatukesalahandidalamsuatuprogramyangmembuatnyamustahil untukdiparsing. Exception: Suatu kesalahan di dalam suatu program yang membuatnya gagal pada waktudijalankan.Biasadisebutruntimeerror. Debugging:Prosesuntukmenemukandanmembuangketigamacamkesalahan.
1.7.Latihan
Latihan1.1 Ilmuwan Komputer mempunyai kebiasaan menggunakan katakata Bahasa Inggris untukmengartikansesuatuyangberbedadenganmaksudBahasaInggrissecaraumum. Sebagaicontoh,didalamBahasaInggris,suatupernyataandansuatukomentaradalah halhampirsamabagusnya,tetapiketikakitasedangberbicarasekitarsuatuprogram, merekaumumnyaberbedabeda. Daftarkatapadaakhirmasingmasingbabdimaksudkanuntukmenyorotikatakatadan ungkapanyangmempunyaiartikhususdidalamilmupengetahuankomputer.Ketika andamelihatkatakatayangtelahdikenal,janganberasumsibahwaandamengetahui 28
apaartinya!
Latihan1.2 Sebelum anda melakukan yang lain, cari tahu bagaimana cara menyusun dan menjalankan Program Java didalam environtment yang anda gunakan. Beberapa environtmentmenyediakancontohprogramyangserupadengancontohpadabagian 1.5. a.KetikprogramHelloWorld,kemudiancompiledanRun. b.TambahkansuatustatemenyangdapatmencetakpesankeduasetelahHelloWorld". Sesuatuyanglucuseperti,Andaapakabar?CompiledanRunlagi. c.TambahkansuatubariskomentarpadaprogramdimanasajadanCompile.LaluRun lagi.Komentaryangbarumestinyatidakmempunyaieffectpadaprogramsetelahdi Run. Latihaninimungkintampaksepele,tetapiituadalahawaldaribanyakprogramyang akankitakerjakannanti.Dalammendebugdenganperceaadiri,andaharusmempunyai percaya diri pada environment pemrograman anda. Dalam beberapa environment, sangatmudahuntukkehilanganjejakprogramyangmanayangsedangdieksekusi,dan anda mungkin menemukannya diri berusaha mendebug suatu program ketika anda menjalankanprogramyanglain.Menambahkan(danmengubah)suatucetakanstatemen merupakan hal yang sederhana untuk menetapkan hubungan antara program yang sedangandaperhatikandankeluarannyaketikaprogramdiRun.
29
Latihan1.3 Adalah suatu hal baik jikaanda melakukan banyak kesalahan, sehingga anda dapat melihatapayangsalahdengancaramelihatpemberitahukesalahanpadacompiler. Kadangkadangcompilerakanmemberitahuandatepatnyaapayangsalah,dananda harus membereskan kesalah itu. Kadangkadang, walaupun demikian, compiler juga akan memberi tahu banyak kesalahan yang tidak semestinya. Anda akan sedikit memakainalarketikaandamempercayaicompilerdanandaharushatihati. a.Hapussalahsatudarikurungkurawalpembuka. b.Hapussalahsatudarikurungkurawalyangterdekat. c.Sebagaigantimain,tulismian. d.Hapuskatastatic. e.Hapuskatapublic. f.HapuskataSystem. g.Gantikanprintlndenganpintln. h.Gantikanprintlndenganprint.Yanginiadalahsuatuhalketatsebabmerupakansuatu kesalahanlogika,bukankesalahansintaksis.StatemenSystem.Out.Printadalah legaltetapimungkiniyaataumungkinbukanapayangandaharapkan. i.Hapussalahsatudaritandakurung.Tambahkanlagilebihdariitu.
30
println adalah singkatan dari print line" sebab setelah masingmasing baris itu ditambahkansuatukhususkhusuyangdinamakannewline,yangmenyebabkancursor untukbergerakkebarisyangberikutnya.SetelahituPrintlndilibatkan,teksyangbaru munculpadabarisberikutnya. Menampilkan output dari banyak cetakan statemen dalam satu baris sangatlah 31
bermanfaat.satubaris.Andadapatmekannyacommandprintberikut:
PrograminiakandicompiledandiRunsamahalnyasebelumnya.Tulisanpadabagian akhir ( newlines) juga tidak mempunyai efek pada program, maka saya bisa sudah menulis:
32
2.2Variabel
Salah satu keunggulan fitur suatu bahasa pemrograman adalah kemampuan untuk memanipulasivariabel.Suatuvariabeladalahlokasiyangmenyimpansuatunilai.Nilai adalahberbagaihalyangdapatdicetakdandisimpan(kitaakanlihatkemudian)yang dioperasikan.Stringyangtelahkitacetak("Hello,World.","Goodbye",dll.)adalah nilai.
Stringfred;
Statemeninimerupakansuatudeklarasi,karenamendklarasikanvariabelbernama fred yang bertipe string. Masingmasing variabel mempunyai suatu tipe yang menentukan tipe nilai apa yang akan disimpan. Sebagai contoh, tipe int dapat menyimpanbilanganbulat,dantidakmungkinakanmenyimpantipestring. 33
Anda akan melihat bahwa beberapa tipe dimulai dengan huruf besar dan beberapa dengan huruf kecil.. Kita akan belajar arti dari perbedaan ini nanti, tetapi untuk sekarangandabenarbenarperluuntukberhatihati.AdatipeselainIntataustring,dan compilerakanmenolakjikaandamencobamembuatsendiritipedata.
Anda mungkin bisa menerkanerka tentang nilai apa yang akan disimpan oleh tipe tersebut.Contohinimemperlihatkansintakuntukmedemonstrasikanberbagaivariabel dengan tipe yang sama: hour dan minute keduaduanya merupakan bilangan bulat (tipeint).
2.3Assignment
Sejakkitasudahmenciptakanbeberapavariabel,kitainginmenyimpansuatunilaipada variabeltersebut.KitaakanmekannyadenganAssignmenStatement.
fred="Hello.";
//givefredthevalue"Hello."
34
hour=11; minute=59;
//assignthevalue11tohour //setminuteto59
ketika anda mendeklarasikan suatu variabel, anda menciptakan suatu nama untuklokasipenyimpanan.
Ketikaandamekanassignmentterhadapsuatuvariabel,andamemberinyasuatu nilai.
Untuk masingmasing variabel, nama variabel nampak di luar kotak itu dan nilai nampakdidalam.
Disisilain,aturanitubisameragukan,karenaadabanyakcarayangdapatandakan
35
dalam mengkonversi nilainilai dari satu tipe ke tipe lain, dan Java kadangkadang mengkonversi berbagai hal secara otomatis. Maka sekarang anda perlu ingat aturan yangumum,dankitaakanmemperbicangkannyasecarakhususnanti.
Hal lain yang meragukan adalah bahwa beberapa string kelihatan seperti bilangan bulat,tetapisesungguhnyabukan.Sebagaicontoh, fred mengandungstring "123", yangmanaterdiridarikarakter1,2dan3,tapiitutidaksamahalnyasepertinomor123.
2.4MencetakVariabel
Anda dapat mencetak nilai suatu variabel menggunakan perintah yang sama seperti yangkitagunakanuntukmencetakStrings.
Programinimenciptakansuatuvariabelyangbernama firstLine,mengassignnyake 36
dalam nilai " Hello, Again!" dan kemudian mencetak nilainya. Ketika kita memperbicangkan tentang mencetak suatu variabel," kita berarti mencetak nilai variabel itu. Untuk mencetak nama suatu variabel, anda harus menaruhnya didalam tandakutip.Sebagaicontoh:System.Out.Println("Firstline");
Jikaandainginlebihdetail,andabisamenulis:
Keluarandariprograminiadalah:
ThevalueoffirstLineisHello,again!
Saya senang untuk mengatakan bahwa sintak untuk mencetak suatu variabel adalah samahalnyadenganmengabaikanjenisvariabelitu.
37
System.out.println(".");
Keluarandariprograminiadalah:Thecurrenttimeis11:59.
PERINGATAN:Iniadalahpraktekumumuntukmenggunakanbeberapaperintahprint yang diikuti oleh println, untuk meletakkan berbagai nilai pada Baris yang sama. Tetapi anda harus hatihati perintah println pada bagian akhir. Pada banyak environment keluaran dari print disimpan tanpa dipertunjukkan sampai perintah printlndilibatkan,dimanakeseluruhanbarisdipertunjukkandengansegera.Jikaanda menghilangkanprintln,programbisaberakhirtanpapernahmempertunjukkankeluaran yangdisimpan!
2.5Keywords
Beberapabagianyanglalu,sayaberkatabahwaandadapatmembuatnamaapapunyang andabutuhkanuntukvariable,tetapiitutidakselalubenar.Adakatakatatertentuyang tersediapadaJavasebabitudigunakanolehcompileruntukmenguraikanstrukturdari programanda,danjikaandamenggunakannyasebagainamavariabel,akanmenjadi kacau.Katakatainidisebut keywords,meliputi public, class, void, int,danbanyak lagiyanglain.
Daftaryanglengkapadatersediapada:
http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html
Lokasiini,yangdisediakanolehSun,meliputiDokumentasiJavayangakanmengacu
38
padakeseluruhanisibuku.
Denganmenghafaldaftaritu,sayajaminandamendapatkeuntungandarifituryang disediakan pada banyak Java Development environment : Kode yang di tampilkan. Dalam mengetik, bagianbagian berbeda dari program anda perlu tampak berbeda warnanya. Sebagai contoh, kata kunci boleh jadi biru, string merah, dan lain kode hitam.Jikaandamengetiksuatunamavariabeldanwarnyabiru,awas!Andamungkin menemukanhalyanganehdaricompileritu.
2.6Operator
Operatoradalahlambangkhususyangdigunakanuntukmempresentasikanperhitungan sederhanasepertipenambahandanperkalian.KebanyakandarioperatordidalamJava persisnyasepertiapayangandainginkan,sebabituadalahlambangmatematikasecara umum. Sebagai contoh, operator untuk menambahkan dua bilangan bulat adalah +. Yang berikut adalah semua ekpresi yang legal menurut Java yang mana artinya kelihatanlebihjelas:
1+1
hour1
hour*60+minute
minute/60
Ungkapan dapat berisi nama dan nomor variabel. Pada setiap kasus nama variabel digantikandengan nilaisebelumperhitungannya dikan.Penambahan,pengurangan dan perkalian semua yang anda inginkan, tetapi anda mungkin dikagetkan oleh pembagian.Sebagaicontoh,programyangberikut:
39
akanmenghasilkankeluaranyangberikut:
Numberofminutessincemidnight:719 Fractionofthehourthathaspassed:0
Ketika kedua operand adalah bilangan bulat (operand adalah suatu operasi pada operator),hasilnyaharusjadisuatubilanganbulat,danbilanganbulatbersifatselalu membulatkan kebawah, bahkan pada kasus seperti ini dimana bilangan bulat yang berikutnyamenjadisangatdekat.
Suatu alternatif yang mungkin dalam hal ini adalah untuk mengkalkulasi suatu persentasedibandingpecahan:
System.out.print("Percentageofthehourthathaspassed:"); System.out.println(minute*100/60);
Hasilnya: 40
Percentageofthehourthathaspassed:98
Lagilagihasildibulatkanbawah,tetapisetidaknyasekarangjawabannyasudahbenar. Dalammemperolehjawabanyanglebihsayaratlagi,kitabisamenggunakansuatutipe variable berbeda, yang disebut floatingpoint, yang mampuuntuk menyimpan nilai yangkecil.Kitaakanmempelajariitupadababberikutnya.
2.7Operasi
Ketikalebihdarisatuoperatormunculpadasuatuekspresi,evaluasibergantungpada nilai precedence. Suatu penjelasan lengkap tentang nilai precedence sangat rumit, namununtukmengetahuinyaandadapatmemulai:
Perkaliandanpembagianmempunyaikedudukanlebihtinggi(dikansebelum) penambahan dan pengurangan. Maka 2*31 hasilnya 5, bukan 4, dan 2/31 hasilnya1,bukan1(ingatbahwapembagianbilanganbulat2/3adalah0).
KapanpunJikaandainginmengesampingkanketentuanketentuannilaiprecende ( atau anda tidak tahu pasti apa hasilnya) anda dapat menggunakan tanda kurung.Ungkapandidalamtandakurungdievaluasiterlebihdahulu,maka2*
41
SecaraumumandatidakbisamelaksanakanoperasimatematikapadaString,sekalipun string kelihatan seperti angkaangka. Yang berikut adalah tidak benar (jika kita mengetahuibahwafredmempunyaitipestring)
fred1
"Hello"/123
fred*"Hello"
Ngomongngomong, dengan memperhatikan ekspresi tersebut dapatkan anda menunjukkanbahwa fred adalahsuatu integer atau string?Tidak.SatuSatunyacara mengetahui jenis suatu variabel adalah dengan melihat tempat dimana variabel itu dideklarasikan.
Menariknya,operator+dapatdikanpadastring,walaupunitutidakkanpersisdengan apayangandaharapkan.Untuk string,operator+menghasilkanpenggabungan,yang berarti menggabungkan dua operand. Sehingga " Hello,"+ " World." menghasilkan string Hello,World.dan fred+ " ism"berartimenambahkanakhiranismitukepada ujungkatafredapapuntipefredinidipakaisebagaiformatbaru.
42
2.9 m p osisi Ko
Sejauhinikitasudahmelihatdiunsurunsursuatuvariabelbahasaprogram,ungkapan, dan statements tertutup, tanpa membicarakan tentang bagaimana cara menggabungkannya.
Salahsatucirridaribahasaprogrampalingbermanfaat adalahkemampuanmereka untuk mengambil satu bagian blok kecil dan menyusunnya. Sebagai contoh, kita mengetahuibagaimanacaramengalikanangkaangkadankitamengetahuibagaimana caramencetaknya,itudapatkitasayakankeduaduanyapadawaktuyangsama:
System.out.println(17*3);
System.out.println(hour*60+minute);
Tetapiandadapatjugamenaruhungkapanpadasembarangtempatpadasisikanandari suatustatementugas:
intpercentage; percentage=(minute*100)/60;
43
PERINGATAN: Ada batas dimana anda dapat menggunakan ungkapan tertentu; khususnya,darisisikiridarisuatutugasstatemenharuslahnamasuatuvariabel,bukan suatuekspresi.Itudisebabkanpadasisiyangkirimenandaiadanyatempatpenyimpanan hasilnantinya.Ungkapantidakmempresentasikantempatpenyimpanan,hanya nilai.Sehinggayangberikutadalahtidakbenar:minute+1=hour;
2.10 Daftar kata
Variabel:Suatunamatempatdimanasuatunilaidisimpan.Semuavariabelmempunyai suatutipe,yangdideklarasikanketikasuatuvariabledibuat.
Value: Suatu angka atau string (atau hal alin yang dinamai kemudian) yang dapat disimpanpadasuatuvariabel.TiapTiapnilaikepunyaansatutipe.
type: Suatu set nilai. Tipe suatu variabel menentukan dalam penyimpanan nilainya. Sejauhini,tipeyangsudahkitalihatadalah integer (intdidalamJava)dan ( string didalamJava.
44
Statement: Satu baris kode yang mempresentasikan suatu perintah atau tindakan. Sejauhini,statemenyangsudahkitalihatadalahdeklarasi,tugas,danstatemencetakan.
Deklarasi: Suatu statemen yang menciptakan suatu variabel baru dan menentukan tipenya
Assigment:Suatustatemenyangmenugaskansuatunilaikepadasuatuvariabel.
Operator:Suatulambangkhususyangmempresentasikansuatuperhitungansederhana sepertiaddition,multiplicationataupenggabunganstring.
Operands:Salahsatudarinilainilaidimanadiatasnyasuatuoperatorberoperasi.
Precedence:Kedudukansuatuoperatorketikasuatuoperasidievaluasi
Concatenate:Untukmenggabungkanujungujungduaoperand.
2.11Latihanlatihan
b.IkuticontohdidalamBagian2.4,tulissuatuprogramyangmenciptakanvariabel nama hari, tanggal/date, bulan dan tahun. hari akan berisi hari minggu dan tanggal/date akan berisi hari pada bulan itu. Apa tipe masingmasing variabel? Berikannilaiuntukvariabelyangmempresentasikantanggal/datesekarang.
c. Cetak nilai dari tiap variabel sejajar dengan dirinya. Ini adalah suatu langkah intermediate yang bermanfaat untuk mengecek yang segalanya yang telah dikan sejauhini.
d.Modifikasiprogramitusedemikianrupasehinggadapatmencetaktanggal/dateitu didalamFormatstandarAmerika:
Wednesday,February17,1999.
e.Modifikasilagiprogramitusedemikianrupasehinggatotalkeluarannyaadalah:
Americanformat: Wednesday,February17,1999
46
Europeanformat: Wednesday17February,1999
Inti dari latihan ini adalah untuk menggunakan penggabungan string untuk menampilkan nilainilai dengan tipe berbeda ( int dan string), dan untuk praktek mengembangkan program secara berangsurangsur dengan menambahkan beberapa statemenpadawaktuyangsama.
Latihan2.2
a.CiptakansuatuprogrambaruyangdinamakanTime.Java.Mulaisekarang,sayatidak akan mengingatkan anda untuk mulai dengan suatu yang kecil, bekerja dengan program,tetapiandasendiriyangmekannya.
b.IkuticontohdidalamBagian2.6,untukmenciptakanvariabelnamajam,menitdan detik/second, dan meng assign nilainya dengan waktu yang sekarang. Gunakan format24jam,sedemikianrupasehinggapada2pmnilaijamadalah14.
c.Buatprogramuntukmengkalkulasidanmencetakbanyaknyadetikmulaidaritengah malam.
d.Buatprogramuntukmengkalkulasidanmencetakbanyaknyadetikyangtersisapada hariitu.
f. Ubah nilainilai jam, menit dan detik untuk mencerminkan waktu yang sekarang (sayaberasumsibahwawaktutelahberlalu),danperiksauntukmeyakinkanbahwa programdapatbekerjadengantepatdengannilainilaiyangberbeda.
48
Di dalambab yangterakhir kitamempunyaibeberapapermasalahan dengan angka angkayangbukanlahbilanganbulat.Kitadisibukkandenganmasalahuntukmengukur persentase sebagai pecahan, tetapi suatu solusi yang lebih umum adalah untuk menggunakan angkaangka floatingpoint, yang dapat mempresentasikan pecahan sepertihalnyabilanganbulat.DidalamJava,tipefloatingpointdisebutdouble.
Andadapatmenciptakanvariabelfloatingdanmemberikannilaidenganmenggunakan Sintakyangsamayang]kitagunakanuntuktipelain.Sebagaicontoh:
doublepi; pi=3.14159;
Inijugabenaruntukmempresentasikankansuatuvariabeldanmenugaskansuatunilai kepadanyapadawaktuyangsama:
intx=1; Stringempty=""; doublepi=3.14159;
Sebenarnya,sintakiniadalahsecaraumum.Suatukombanisiassigmentdandeklarasi terkadangdisebutsuatuinitialisasi. 49
Walaupun angkaangka floatingpoint bermanfaat, namunn sering suatu source membingungkankarenasepertinyaadatumpangtindihantarabilanganbulatdanangka angkafloatingpoint.Sebagaicontoh,jikaandamempunyainilai1,yangmerupakan suatubilanganbulat,bilanganfloatingpoint,ataukeduaduanya?
Pada dasarnya, Java menilai integer itu 1 dan floatingpoint 1.0, sungguhpun sepertinyaadalahjumlahnyasama.Tetapitipenyaberbeda,danpadadasarnya,anda tidaklahdiijinkanuntukmengassignantaratipe.Sebagaicontoh,yangberikutadalah tidakbenar:
intx=1.1;
doubley=1;
doubley=1/3;
50
Anda mungkin mengharapkan variabel y diberi nilai 0.333333, benar, tetapi sesungguhnya akan menghasilkan nilai 0.0.Alasan adalah bahwa ekspresi pada sisi kanan nampak seperti perbandingan dua bilangan bulat, maka Java mengerjakan pembagianbilanganbulat,yangmenghasilkanbilanganbulat0.yangdikonversiUntuk floatingpointhasilnya0.0. Satu cara untuk memecahkan masalah ini ( saat anda menggambarkan apa artinya) adalahuntukekspresifloatingpointdarikanan.
doubley=1.0/3.0;
disiniydisetmenjadi0.333333,yangdiharapkan.
Semuaoperasiyangtelahkitalihatsejauhinipenambahan,pengurangan,perkalian,dan pembagianjugaadapadanilaifloatingpoint,walaupunandamungkintertarikuntuk mengetahui bahwa mekanisme dasarnya berbeda sepenuhnya. Pada kenyataanya, prosesormempunyaiperangkatkeraskhusushanyauntukmekanoperasifloatingpoint.
3.2Mengkonversidoublekeint
Sepertisayasebutkan,Javamengkonversi int ke double secaraotomatisjikaperlu, sebab tidak ada informasi hilang dari konversi itu. Pada sisi lain, mengubah suatu double kesuatu int memerlukan penyelesaian. Javatidakmelaksanakan operasiini secaraotomatis,sebagaiprogrammer,andamenyadarihilangnyasebagianjumlahdari angkaitu.
Carayangpalingsederhanauntukmengkonversisuatufloatingpointkesuatubilangan 51
intx=(int)Math.PI;
Operatorintmempunyaiefekmengikutibilanganbulat,makaxmenghasilkannilai3.
Typecasting harus didahulukan sebelum operasi perhitungan, maka didalam contoh yangberikut,nilaiPI(22:7)menghasilkanpertamadikonversikesuatubilanganbulat, danhasilnyaadalah60,bukan62.
intx=(int)Math.PI*20.0;
Mengubahkesuatubilanganbulatselaludibulatkankebawah,sekalipunpecahannya 0.99999999.
Duapropertiesini(precedencedanpembulatan)dapatmembuattypecastkurangbagus.
3.3MethodMatematika
Didalammatematika,andamungkinsudahmelihatfungsisepertisindanlog,dananda 52
sudahmempelajariekspresisepertisin(/2)danlog(1/x).Pertama,andamengevaluasi ekspresididalamtandakurung,yangmanadisebutargumentasifungsi.Sebagaicontoh,
/2kirakira1.571,dan1/xadalah0.1(diasumsikanbahwax10).
Kemudianandadapatmengevaluasifungsiitudenganmenggunakantabelataudengan mekanberbagaiperhitungan.Sin1.571adalah1,danlog0.1adalah1(diasumsikan bahwalogmengindikasikanbilanganpokok10). Prosesinidapatditerapkanberulangkaliuntukmengevaluasiekspresiyanglebihrumit seperti log(1/ sin(/2)). pertama kita mengevaluasi argumentasi function, lalu mengevaluasifungsiyangpalingdalam,danseterusnya.
Java menyediakan satu set builtin fungsi yang mengandung kebanyakan operasi matematikan yang anda tahu. Fungsi ini disebut methods. Kebanyakan method matematikaberoperasipadadouble.
Method matemmatika dilibatkan menggunakan suatu sintaksis yang serupa dengan perintahprintyangkitalihat:
53
fungsitrigonometriclain(cos,Tan)adalahdidalamradian.Untukmengkonversidari derajat ke radian, anda dapat membagi dengan 360 dan mengalikan dengan 2. Untungnya,Javamenyediakansebagainilaiyangbuiltin:
PI(22:7)adalahdalamhurufbesar.JavatidakmengenaliPi(22:7),Pi(22:7),ataupie.
MetodabermanfaatlaindidalamClaasadalahputaran,yangmengelilingisuatunilai floatingpointkepadabilanganbulatyangpalingdekatdankembalikankesuatuint.
doubledegrees=90; doubleangle=degrees*2*Math.PI/360.0;
intx=Math.round(Math.PI*20.0);
Dalamhaliniperkaliandikanterlebihdulu,sebelummethoddilibatkan.hasilnyaadalah 63(yangdibulatkandari62.8319).
3.4Composition
Sama halnya dengan fungsi matematika, Method Java dapat composed, maksudnya andamenggunakansatuekspresisebagaibagiandariyanglain.Sebagaicontoh,anda dapatmenggunakanekspresimanapunsebagaisuatuargumentasikesuatumetoda:
doublex=Math.cos(angle+Math.PI/2);
Statemen ini mengambil nilai Math.Pi, membaginya dengan dua dan menambahkan hasilnya kepada nilai variabel angle. Penjumlahan kemudian melewatkan suatu 54
argumentasiuntukmethodcos.(ingatPI(22:7)ituadalahnamasuatuvariabel,bukan method,makatidakadaargumentasi,bukanpulaargumentasiyangkosong()).
Andadapatjugamengambilsatumethoddanmelewatkannyapadaargumentasikelain:
doublex=Math.exp(Math.log(10.0));
Didalam Java, log berfungsi selalu menggunakan dasar e, maka statemen ini mengartikandasarloge10dankemudianmenaikkane.Hasilnyadiassignkex;saya berharapandamengetahuiapaartinya.
3.5Menambahkanmetodebaru
Sejauh ini kita hanya menggunakan metoda yang dibangun dalam Java, tetapi memungkinkanuntukmenambahkanmetodabaru.Sebenarnyakitamelihatsatumetoda definisi: main. Method dinamakan main khusus menandai di mana pelaksanaan programdimulai,tetapisintakuntukyangmainadalahsamadengandefinisimetoda lain:
publicstaticvoidNAME(LISTOFPARAMETERS){ STATEMENTS }
Andadapatmembuatnamaapapunyangandabutuhkanuntukmetodaanda,kecuali namamainataukeywordjavalainnya.Daftaryangmenginformasikantipeparameter, 55
bilaada,andaharusmenyediakanuntukpenggunaanfungsiyangbaru.
ParametertunggaluntukmainadalahString[]args,yangmenunjukkanbahwasiapapun menggunakanmainharusmenyediakansuatuarrayString(akandipelajaripadaBab 10). Sepasang metoda yang pertama yang akan kita tulis tidak punya parameters,sehinggasintaknyakelihatansepertiini:
publicstaticvoidnewLine(){ System.out.println(""); }
MethodinidinamainewLine,dantandakurungyangkosongmenunjukkanbahwaia tidakmengambilparameterapapun.Methodituhanyaberisistatementunggal,yang mencetaksuatu stringkosong yangditandai oleh"".Pencetakan suatustring dengan tidakadahurufdidalamnyatidakakannampakbermanfaat,kecualiingatbahwaprintln melompatibarisyangberikutnyasetelahitumencetak,makastatemeninimempunyai efekmelompatibarisyangberikutnya.
Didalammainkitadapatmembuatmethodyangbaruinimenggunakansintakyang serupadenganmemakaiperintahJavayangsudahbuiltin:
56
Keluarandariprograminiadalah
Firstline. Secondline.
Perhatikanspasiantarakeduabentuk.Akibatnyabagaimanajikakitainginmenambah spasiantaraduabaris?Kitabisamemanggilmethodyangsamaberulangkali:
AtaukitabisamenulissuatumetodabaruyangdinamakanthreeLineyangmencetak tigabentukbaru:
57
System.out.println("Secondline."); }
Andaperlumemperhatikanbeberapahalsekitarprogramini:
Andadapatmemanggilproseduryangsamaberulangkali.Sebenarnya,ituumumnya bergunabagimekannya.
Anda bisa mempunyai satu method memanggil metoda lain. Dalam hal ini, main meminta threeLine dan threeLine meminta newLine. Lagilagi ini umumnya bermanfaat.
DidalamthreeLinesayamenulistigastatemensemuapadabarisyangsama,yangmana secara yg sintak benar (ingat bahwa spasi dan baris baru pada umumnya tidak mengubah artidari suatu program).Disisilain,itu suatugagasan yangbaik untuk menaruh statemen masingmasing sejajar dengan barisnya, untuk membuat program anda mudah dibaca. Saya terkadang menggunakan aturan dalam buku ini untuk menghematruang.
1.Menciptakansuatumethodbarumemberiandasuatukesempatanuntukmemberi suatu nama kepada satu kelompok statemen. Method dapat menyederhanakan suatu programdenganmenyembunyikansuatuperhitungankompleksdibelakangperintah 58
tunggal,dandenganpenggunaankataBahasaInggrissebagaipenggantikode.Lebih jelasnya,newLineatauSystem.Out.Println("")?
3.6Classdanmethod
Dari pengelompokkan kodekode dari bagian yang sebelumnya, maka keseluruhan definisikelaskelihatansepertiini:
publicstaticvoidthreeLine(){ newLine();newLine();newLine(); }
59
Barisyangpertamamenunjukkanbahwainiadalahdefinisiuntuksuatukelasyangbaru yangdinamakanNewline.SuatuClassadalahsuatukumpulandarisuatumethodyang berelasi. Dalam hal ini, kelas yang bernama Newline berisi tiga metoda, yang dinamakannewLine,threeLine,danmain.
ClasslainyangtelahkitalihatadalahMathKelas.Classituberisimethodyangbernama sqrt,sin,danbanyakyanglain.Ketikakitamemanggilsuatufungsimatematika,kita harus menetapkan nama Class (Math) dan nama fungsinya. Itulah mengapa sintak berbedauntukmasingmasingmethodbuiltindanmetodayangkitatulis:
Math.pow(2.0,10.0); newLine();
JikaandamencobauntukmemanggilsuatumethoddariClassyangsalah,compilerakan menghasilkansuatukesalahan.Sebagaicontoh,jikaandaketik:
pow(2.0,10.0);
Compilerkirakiraakanmengatakan,Tidakbisamenemukansuatumethodbernama powdidalamClassNewline."Jikaandasudahmelihatpesanini,andamungkinheran
60
mengapacompilermencaripowdidalamClassyangdidefinisikan.Sekarangandasudah tahu.
3.7Programdenganbanyakmethod
Ketika anda memperhatikan suatu Class yang didefinisikan yang berisi beberapa method, ketika dicoba untuk membacanya dari atas sampai ke bawah, namun nampaknyamembingungkan,sebabitubukanlahOrderOfExecutiondariprogram. Eksekusi selalu dimulai pada awal dari statemen dari main, dengan mengabaikan dimanaprogramnya(dalamhalinisayadenganbebasmenaruhnyapadabagianbawah). Statemen dieksekusi satu per satu secara berurutan, sampai anda menjangkau suatu methodyangdituju.Methodsepertisuatubelokandidalamalureksekusi.Setelahitu akanberlanjutkestatemenyangberikutnya,andapertamaakankebarisyangpertama dari metoda yang dilibatkan, mengeksekusi semua statemen disana, dan kemudian kembalidanmengambillagidimanaandaberhenti.
Kelihatannya cukup sederhana, namun anda harus ingat bahwa satu method dapat memanggilmethodyanglain.Sepertiitu,selagimasihpadamain,kitamungkinharus berhenti dan melaksanakan statemen pada threeLine. Tetapi ketika kita sedang melaksanakan threeLine, kita mendapatkan interupsi tiga kali untuk berhenti dan melaksanakannewLine.
Padabagianini,newLinememanggilmethodprintlnyangsudahbuiltin,yangberbelok ke hal lain.Kebetulan,Javasungguhahlipadamengawasidimanaitu,makaketika println selesai, lalu mengambil kembali eksekusi dimana newLine berhenti, dan
61
kemudiankembalilagikepadathreeLine,dankemudianakhirnyakembalilagikepada mainsehinggaprogramdapatberakhir. Sebenarnya,secarateknisprogramtidakberakhirpadaujungmain.Sebagaigantinya, eksekusimengambildimanaprogramituberhentimengeksekusiyangmelibatkanmain, yang merupakan Interpreter Java. Interpreter Java mengasuh macam hal suka menghapuswindowdancleanupumum,dankemudianprogramberakhir.
Apa hal yang tidak baik untuk dikan dalam mempelajari buku ini? Ketika anda membaca suatu program, jangan membaca dari atas sampai ke bawah. Sebaiknya mengikutialurpelaksanaan.
3.8Parameterdanargumen
Sebagiandarimethodbuiltinyangsudahkitagunakanmempunyaiparameter,yang bernilaibahwa andamembiarkanmethodmekanpekerjaanitu.Sebagaicontoh,jika anda ingin menetukan 30 Method sinus suatu angka, anda harus menandai apa angkanya.lalu,sinmengambilsuatunilai doublesebagaiparameter.Untukmencetak suatustring,andaharusmenyediakanstring,yangmanaprintlnmengambilsuatuString sebagaiparameter.
Beberapamethodmengambilparameterlebihdarisatu,sepertipow,yangmengambil duadouble,yaitubasedaneksponen.Perhatikanbahwapadasetiapkasusinikitaharus menetapkantidakhanyaberapabanyakparameteryangada,tetapijugatipeparemater. Maka seharusnya itu tidak mengejutkan anda ketika anda menulis suatu Class 62
definition,daftarparametermenandaitipeparametermasingmasing.Sebagaicontoh:
Metoda ini mengambil parameter tunggal yang dinamai phil, yang mempunyai tipe String.
Apapunparameternya(dalamposisiinikitatidakmenyatakanapaparameternya),akan dicetakduakali.Sayamemilihnamaphiluntukmenyatakanpadaandabahwanama yang anda berisuatu parameterterserahanda, tetapisecaraumum andasebaiknya memilihsesuatuyanglebihilustratifdibandingphil. Untukmemanggilmethodini,kitaharusmenyediakansuatu String.Sebagaicontoh, kitamungkinmempunyaisuatumethodmainsepertiini:
publicstaticvoidmain(String[]args){ printTwice("Don'tmakemesaythistwice!"); }
String yangandabuatdisebutsuatuargument,dankitamengatakanbahwaargument diberikanpadamethod.Dalamhalinikita akanmenciptakansuatunilai string yang berisi teks "Don't make me say this twice!" dan melewatkan string sebagai suatu
63
argumentikeprintTwicedimana,berlawanandenganyangdiinginkan,danakandicetak duakali.
Sebagai alternatif, jika kita mempunyai suatu Variabel String, kita bisa menggunakannyasebagaigantisuatuargument:
Perhatikansesuatuyangsangatpentingdisini:namavariabelyangkitalewatkansebagai suatuargument(argument)tidakmekanapaapaterhadapparameter(phil).
Sayakatakanlagibahwa:
Namavariabelyangkitalewatkansebagaisuatuargumenttidakmekanapapun terhadapnamaparameter.
Nilaiyangandanyatakansebagaisuatuargumentiharusmempunyaitipeyangsama denganparametermethodyangandapanggil.Aturaninisangatpenting,tetapihalini 64
seringmembuatkitabingungpadaJavauntukduapertimbangan:
Jikaandamembuatkesalahanpadaaturan,compilerseringmenghasilkansuatuhalyang kacau pada pemberitahu kesalahan. sehingga, Anda sering mendapati bermacam kesalahan argument pada method ini ," itu mungkin karena efek dari tidak ditemukannya suatu metoda dengan nama dan tipe itu. Sekali anda menemukan pemberitahu kesalahan ini maka anda akan menggambarkan tahu bagaimana cara menginterpretasikannya.
3.9Stackdiagram
Parameter dan variabel lain hanya ada di dalam methodnya sendiri. Di dalam membatasimain,tidakadahalsepertiphil.Jikaandamencobauntukmenggunakanitu, compilerakanmenganggapnyasalah.Dengancarayangsama,didalamprintTwice tidakadahalsepertiargument.
Satucarauntukmengetahuidimanamasingmasingvariabeldidefinisikanpadasuatu stackdiagram.
StackDiagramuntukcontohyangsebelumnyakelihatansepertiini:
65
3.10MetodeDenganBanyakParameter
Sintak untuk mendeklarasikan dan memanggil method dengan berbagai parameter adalah suatu sumber kesalahan pada umumnya. Pertama, ingat bahwa anda harus mendeklarasikantipetiaptiapparameter.Sebagaicontoh
Itubisajaditerkecohuntukmenulisintjam,menit,tetapiformatituhanyabenaruntuk mendeklarasikanvariabel,bukanuntukparameter.
Sumber kesalahan umum yang lain adalah bahwa anda tidak punya sesuatu untuk 66
mendeklarasikantipeargument.Yangberikutadalahsalah!
Dalam hal ini, Java dapat mengatakan bahwa tipe dari hour dan minute dengan memperhatikandeklarasinya.Jugatidaklegaldantidakbenarmemasukkannyaketika andamelewatkannyasebagiargument.SintaksisyangbenaradalahprintTime(hour, minute).
Latihan3.1Gambarsuatuframestackyangmenunjukkanstatusprogramketikamain memanggilprintTimedenganargumentasi11dan59.
3.11Methoddanhasilnya
Andamungkinsudahmemperhatikansebagiandarimethodyangtelahkitagunakan, sepertimethodMath,menghasilkanhasil.Methodlain,seperti println dan newLine, meng eksekusi beberapa action tetapi mereka tidak mengembalikan suatu nilai. itu memunculkanbeberapapertanyaan:
67
Apayangterjadijikaandamenggunakansuatumethodprintsebagaibagiandari suatuekspresisepertiSystem.Out.Println("boo!")+7?
Dapatkah kita menulis method yang menghasilkan hasil, atau kita tetap menggunakannewLinedanprintTwice?
Jawaban bagi pertanyaan ketiganya adalah ya, anda dapat menulis method yang mengembalikan nilai," dan itu akan kita pelajari dalam 2 bab. Saya akan meninggalkannya untuk anda coba jawab. Sebenarnya, kapan saja anda mempunyai suatupertanyaantentangapayanglegaldanillegallebihbaikjikamencobanyapada compiler.
3.12Daftarkata
floatingpoint:Suatujenisvariabel(ataunilai)yangdapatberisipecahansepertihalnya bilanganbulat.DidalamJawatipeinidisebutdouble.
Class:Suatukoleksiyangdinamaimethod.Sejauhini,kitasudahmenggunakanClass Math dan Class System, dan kita sudah menulis Classs dengan nama Hello dan Newline.
method: Penamaan suatu urutan statemen yang melaksanakan beberapa fungsi bermanfaat.Metodabolehataubolehtidakmengambilparameter,danbolehatauboleh tidakmenghasilkansuatuhasil.
Parameter:Suatupotonganinformasiyangandamenyediakanuntukmemanggilsuatu
68
metohd. Parameteradalahsepertivariabeldidalamnyanilainilaidanmempunyaitipe.
Argument:Suatunilaiyangandasediakanketikaandamemanggilsuatumethod.Nilai iniharusmempunyaitipeyangsamaparameteryangbersangkutan.
invoke:Menyebabkansuatumethoduntukdieksekusi
3.13Latihan
Latihan3.2
Latihaniniadalahuntukmempraktekkanmembacakodedanuntukmeyakinkanbahwa andamemahamialureksekusimelaluisuatuprogramdenganberbagaimethod.
69
publicstaticvoidzoop(){ baffle(); System.out.print("Youwugga"); baffle(); } publicstaticvoidmain(String[]args){ System.out.print("No,I"); zoop(); System.out.print("I"); baffle(); } publicstaticvoidbaffle(){ System.out.print("wug"); ping(); } publicstaticvoidping(){ System.out.println("."); }
a.Tulisbarisyangpertamasuatumetodanamazoolyangmengambiltigaparameter: suatuintdanduaString.
70
b. Tulis satu baris kode yang memanggil zool, ketika melewatkan suatu argument dengannilai11,namabinatangkesayanganandayangpertama,dannamajalanyang adaditempatandaketikaandadibesarkan.
Latihan3.4
Tujuan latihaniniadalahuntukmengambil kodedari suatulatihansebelumnyadan mengemasnya didalam suatu method yang mengambil parameter. Anda perlu mulai bekerjamenemukansolusidariLatihan2.1.
a. Tulis suatu method untukmemanggil printAmerican yang mengambil day, date, monthdanyearssebagaiparameterdandicetakdidalamFormatAmerika.
Wednesday,September29,1999
c.AndasudahmempunyaidebugprintAmerican,tulismethodlainuntukmemanggil printEuropeanyangdicetakdidalamFormatEropa.
Latihan3.5
Banyakperhitungandapatdinyatakandengansingkatmenggunakanmultadd"operasi, 71
yang mengambil tiga operand dan menghitung a*b+ c. Beberapa prosessor menyediakan implementasi perangkat keras dari operasi ini untuk angkaangka floatingpoint.
a.BuatsuatuprogrambarudengannamaMultadd.Java.
b. Tulis suatu method dengan nama multadd yang mengambiltiga double sebagai parameterdancetakmultadditionationnya . c. Tulis suatu method main yang menguji multadd dengan memanggilnya dengan beberapaparametersederhana,seperti1.0,2.0,3.0,dankemudiancetakhasilnya,dan harus5.0.
d.Jugadidalammain,gunakanmultadduntukmenghitungnilainilaiyangberikut:
e.Tulissuatumethodyangbernamayikesyangmengambildoublesebagaiparameter dangunakanmultadduntukmengkalkulasidancetak
SYARAT:MethodMathuntukmenaikkannilaieadalahMath.Exp.
72
73
intquotient=7/3; intremainder=7%3;
Operator yangpertama, pembagian bilanganbulat,menghasilkan 2.Operator yang keduamenghasilkan1.Dengandemikian,7yangdibagioleh3adalah2dengansisa1. Operator modulus ternyata adalah anehnya bermanfaat. Sebagai contoh, anda dapat memeriksaapakahsatubilangan;jumlahadalahdapatdibagiolehlain:jikax%yadalah nol, kemudian x dapat dibagi dengan y. Juga, anda dapat menggunakan operator modulusuntukmengetahuidigitpalingkanandarisuatubilangan.Sebagaicontoh,x% 10menghasilkandigitxpalingkanan(di(dalam)basis10).Dengancarayangsamax% 100menghasilkanduadigitterakhir.
4.2 Percabangan
Dalammenulisprogramyangbetulbetulfungsionalt,kitahampirselalumemerlukan kemampuan untuk memeriksa kondisikondisi tertentu dan merubah aliran program. Pernyataan percabangan memberi [kita/kami] kemampuan ini. Format yang paling
74
sederhanaadalahifstatemen:
if(x>0){ System.out.println("xispositive"); }
Dua sisi suatu kondisi operator harus memiliki tipe yang sama. Anda hanya dapat membandingkanintkeintdandoubledengandouble.Sungguhsial,dalamposisiini 75
andatidakbisabandingkanstringsamasekali!Adasuatu[jalan/cara]untukbandingkan stringtetapikitatidaktakkanmembahasnyapadababini.
4.3EksekusiAlternatif
Bentuk kedua dari percabangan adalah pelaksanaan alternatif, di mana ada dua kemungkinan,dankondisimenentukanyangmanayangakandieksekusi. Sintaksnyasepertidibawahini:
76
System.out.println("xisodd"); } }
printParity(17);
Selalu ingat bahwa ketika anda mengeksekusi suatu metoda, anda tidak harus mendeklarasikantipeargumenyangandasediakan.Javadapatmengetahuitipedata tersebutsecaraotomatis.Andaseharusnyapenulisanseperti:
intnumber=17; printParity(intnumber);//WRONG!!!
4.4PercabanganBerantai
Kadangkadangandainginmelihatkemungkinansejumlahkondisikondisiterkaitdan memilih salah satu dari beberapa tindakan. Satu cara untuk melakukan ini adalah denganrangkaianifdanelsesepertiberikut:
77
}else{ System.out.println("xiszero"); }
Rantai ini dapat sepanjang yang anda inginkan, walaupun pada akhirnya akan sulit dibaca.Satucarauntukmembuat[mereka/nya]lebihmudahuntukdibacaadalahuntuk menggunakanstandardindentasi[seperti/ketika]dipertunjukkancontohini.Jikaanda meletakkansemuastatementdankurungkurawaldalamsatubaris,andamemilikilebih sedikitkemungkinanuntukmembuatkesalahansintaksdanandadapatmenemukannya denganlebihcepat.
4.5PercabanganBersarang
Sebagai tambahan terhadap yang percabangan berantai, anda dapat juga membuat percabanganbersarangdidalamyanglain.Kitabisamenuliscontohyangsebelumnya dengan:
78
Sekarangadasuatupercabanganluaryangberisiduacabang.Cabangyangpertama berisi suatu statemen cetakan sederhana, tetapi cabang yang kedua berisi yang pernyataanbersyaratlain,yangmempunyaiduacabang.Kebetulan,dua cabangitu adalah keduaduanya statemen cetakan, walaupun mereka mungkin bisa juga pernyataanbersyaratyanglain.
Perhatikan lagi indentasi membuat struktur lebih enak dibaca, tetapi meskipun demikian, percabangan bersarang lebih susah dibaca dengan cepat. Secara umum, merupakansuatuideyangbaikuntukmenghindarinyaketikaandabisa.
Di lain pihak , struktur tersarang macam ini adalah umum, dan kita akan segera melihatnyalagi.
4.6 The return statement
Statemenkembalian mengijinkanandauntukmengakhiripelaksanaansuatumetoda sebelum anda menjangkau akhir pernyataan. Satu alasan untuk menggunakan nya adalahjikaandamendeteksisuatukondisikesalahan:
79
TerdapatsuatumetodabernamaprintLogarithmyangmengambilsuatutipedatadouble
bernama x sebagai parameter. Hal yang mulamula ia kerjakan adalah memeriksa apakah x kurang dari atau sama dengan nol, dalam hal ini ia mencetak suatu pemberitahukesalahandankemudianmenggunakanpernyataanreturnuntukkeluardari metode. Alir pelaksanaan dengan seketika kembali ke pemanggil dan sisa metoda tidaklahdieksekusi.
Sayamenggunakansuatunilaifloatingpointpadasisikanankondisisebabadasuatu variabelfloatingpointpadasisikiri.
4.7KonversiTipe
Andamungkiningintahubagaimanaandasuatupernyataanseperti"Thelogofxis"+ result,bisadieksekusitanpakesalahanpadahalsalahsatuoperanadalahsuatuString danlainadalahdouble.DalamhaliniJavasecaracerdasmengubahdoublemenjadi StringsebelummengerjakanpenggabunganString.
Yanglebihseringterjadiadalahkenyamananlahyangmenang,yangbiasnayabaik untukparaprogrammerahli,tetapitidakbaikuntukparaprogrammerpemula.Dalam buku ini saya sudah mencoba untuk menyederhanakan berbagai hal dengan menekankanaturandanpenghilanganbanyakperkecualian.
80
4.8Recursion
Saya menyebutkanpada babyangterakhir bahwadiperbolehkan satumetodauntuk memanggilmetodeyanglain,dankitasudahmelihatbeberapacontohmenyangkutitu. Saya lupa untuk menyebutkan bahwa juga diperbolehkan suatu metoda untuk memanggil dirinya sendiri. Mungkin tidak jelas mengapa itu suatu hal baik, tetapi ternyataituadalahsalahsatudarihalyangyangmenarikdanajaibyangsuatuprogram dapatlakukan.
Sebagaicontoh,lihatdimetodayangberikut:
81
Nama metoda adalah countdown dan mengambil bilangan bulat tunggal sebagai parameter.Jikaparameteradalahnol,iaencetakkataBlasto."jikatidakiamencetak bilanganbulattersebutdanmemanggilsuatumetodacountdownkembalidengann1 sebagaiargumen.
Apayangterjadijikakitamemanggilmetodaini,di(dalam)main:
countdown(3);
Eksekusicountdowndimulaidengann=3,dankarenanbukanlahnol,iamencetaknilai 3,dankemudianmemanggildirinyasendiri... Pelaksanaan countdown dimulai dengan n=2, dan karena n bukanlah nol, iamencetaknilai2,dankemudianmemanggildirinyasendiri... Pelaksanaancountdowndimulaidengann=1,dan karenanbukanlahnol,iamencetaknilai1,dankemudian memanggil[dirinya]sendiri... Pelaksanaancountdowndimulaidengann=0,dan karenanadalahnol,iamencetakkataBlastoff" kemudiankembalipadametodeyangmemanggilnya.
82
1 Blastoff!
Sebagaicontohkedua,marikitalihatlagidimetodanewLinedanthreeLine.
Walaupunmetodediatasdapatbekerja,merekatidakakanbanyakbergunajikasaya inginmencetak2barisatau106.Suatualternatiflebihbaikadalahdengan
Programinisangatserupa;sepanjangnadalahlebihbesardarinol,iamencetaksatu newline, dan kemudian memanggil dirinya sendiri untuk mencetak n1 tambahan newlines.Sehingga,totaljumlahnewlinesyangdicetakadalah1+(n1),yangadalah samadengann.
83
Proses suatu pemanggilan metoda terhadap dirinya sendiri disebut recursion, dan . Metodesepertiitudisebutrecursive.
4.9DiagramStackUntukMetodeRekursif
Di (dalam) bab yang sebelumnya kita menggunakan suatu diagram stack untuk menampilkanstatussuatuprogramselamapemanggilansuatumetoda.Diagramyang samadapatmembuatlebihmudahuntuk menginterpretasikansuatumetodarekursif.
Ingat bahwa setiap kali suatu metoda dipanggil ia menciptakan instance baru yang berisivariabellokaldanparameterbaru.Gambarberikutadalahdiagramstackuntuk countdown,dengann=3:
Terdapat satu instance main dan empat instance countdown, masingmasing dengan suatunilaiberbedauntukparametern.Stackterbawah,countdowndengan n=0adalahkasusdasar.Sehinggaiatidakmembuatsuatupanggilanrekursif,jaditidak ada lagi instance countdown. Main adalah kosong sebab main tidak mempunyai 84
parameteratauvariabellokalapapun.
Latihan 4.1 Gambar suatu diagram stack yang menunjukkan status program setelah mainmemanggilnLinesdenganparametern=4,tepatsebeluminstanscenLinesterakhir dikembalikan.
4.10KonvensidanDivineLaw
Didalambagianterakhir,sayamenggunakanungkapanbyconventionbeberapakali untuk menandai (adanya) keputusan disain sewenangwenang tanpa pertimbangan penting,tetapihanyadikatakanberdasarkankonvensi.
Divine Law: Ini adalah ungkapan saya untuk menandai aturan yang benar karena beberapa prinsip logika atau matematika, maka itu adalah benar juga untuk bahasa program(atausistemformal)apapun.Sebagaicontoh,tidakadacarauntukmenentukan ukurandanpenempatansuatukotakmenggunakanlebihsedikitdariempatpotongan informasi.Contohlainadalahbahwamenambahkanbilanganbulatadalahkomutatif. HaliniadalahbagiandaridefinisipenambahandansamahalnyadenganJava.
penggabunganString.
GayaDanKonvensi:Adabanyakaturanyangtidaklahdipaksaolehcompiler,tetapiitu adalah penting untuk penulisan program yang benar, sehingga dapat didebug dan dimodifikasi,dandapatdibacaoranglain.Contohnyaadalahindentasidanpenempatan kurungkurawal,dankonvensiuntukmenamaivariabel,metodadankelas.
4.11DaftarKata
modulus:Suatuoperatoryangbekerjapadabilanganbulatdanmenghasilkansisa ketikasatubilangandibagiolehlain.Di(dalam)Javahaliniditandai tandapersen(%). conditional:Suatublokstatemenyangbolehatautidakbolehdieksekusi tergantung padasuatukondisi. chaining: Suatu cara untuk menggabungkan beberapa pernyataan bersyarat dalam suatuurutan. nesting: Meletakkan pernyataan bersyarat di dalam satu atau kedua cabang dari pernyataanbersyaratlain. coordinate: Suatu variabel atau nilai yang menunjukkan lokasi dari jendela grafis duadimensi. pixel:satuankoordinatdalamkomputer dengan
86
boundingbox:caraumumuntukmenentukankoordinatsuatuareasegiempat. typecast : operatoryangmengkonversidarisatutipedata ketipedatayanglain. DidalamJavadengantipedatadalamtandakurungsseperti(int). interface:Deskripsitentangparameteryangdibutuhkanolehsuatumetodedan tipe datanya prototype: Suatu cara untuk menggambarkan metode menggunakan sintaks yang miripJava. recursion: Proses yang memanggil metoda yang sama dengan yang sekarang dieksekusi. infiniterecursion:Suatumetodayangmemanggildirinyasendirisecaraberulangtanpa pernahberhenti.HalsepertiinibiasanyamenghasilkanStackOverFlowException.
fractal: Semacam gambaran yang adalah didefinisikan secara berulang, sedemikian sehingga masingmasing bagian dari gambar adalah suatu versi yang lebih kecil keseluruhan.
4.12Latihan
Latihan4.2 Jikaandadiberitigatongkat,andamungkinbisaatautidakbisamenyusunnyadalam suatusegitiga.Sebagaicontoh,jikasalahadalah12incidanyanglainadalahsatuinci ,jelas bahwa anda tidak akan bisa membuat ketiganya menjadi segitiga. Berapun panjangnya,adasuatutestsederhanauntukmelihatapakahmungkinuntukmembentuk suatusegitiga:
Jikaterdapatdariketigatongkattersebutyangpanjangnyalebihbesardarijumlahdua
87
yang lain, maka anda tidak dapat membentuknya menjadi segitiga, jika tidak maka merekadapatdibentuksebagaisegitiga"
Tujuanlatihaniniadalahuntukmenggunakanpernyataanbersyaratuntukmenulissuatu metodayangmengembalikansuatunilai.
publicclassBuzz{ publicstaticvoidbaffle(Stringblimp){ System.out.println(blimp); zippo("ping",5); } publicstaticvoidzippo(Stringquince,intflag){ if(flag<0){ System.out.println(quince+"zoop"); }else{ System.out.println("ik"); baffle(quince); System.out.println("boowahaha");
88
} } publicstaticvoidmain(String[]args){ zippo("rattle",13); } }
a. Tulis angka 1 di sebelah statement program yang akan pertama kali dieksekusi. Perhatikanuntukmembedakanhalyangmerupakanstatementdarihalyangbukan. b.Tulisnomor2disampingstatementyangdieksekusipadakalikedua,danseterusnya sampaiakhirprogram[itu].Jikasuatustatemendieksekusilebihdarisekali,itubisa berakhirdenganbillanganlebihdarisatudisampingnya. c.berapanilaiblimpketikabaffledieksekusi? d.Apayangkeluaranprogramini?
Latih4.4 Sajakpertamanyanyian99BottlesofBeeradalah:
Tulis suatu program yang mencetak keseluruhan lirik lagu 99 Bottles of Beer. Program anda harus berisi metode rekursif yang bukan merupakan hal yang susah, mungkinandajugainginmenulismetodetambahanuntukmemisahkanfungsifungsi utamaprogram.
Ketika anda menulis kode, anda akan mungkin ingin mengujinya dengan ejumlah bilangankecilseperti3BottlesOfBeer."
Tujuan latihan ini adalah untuk mengambil suatu masalah dan memecahkannya ke dalampermasalahanlebihkecil,danuntukmemecahkanpermasalahankecildengan menulismetodesederhanayangdapatdidebugdenganmudah.
Latihan4.5 Apayangprogramyangberikut?
90
Latihab4.6 TeoremaFermatyangmenyatakanbahwatidakadabilanganbulata,b,dancsehingga
kecualikasusketikan=2.
Tulis suatu metoda bernama checkFermat yang mengambil empat bilangan bulat sebagaiparametera,b,cdannyangmemeriksauntukmelihatapakahteoriFermat benar.Jikanadalahlebihbesardari2dan ternyataadalahbenaran+bn=cn,programakanmencetakTeori, Fermatadalahsalah!"JikatidakprogramakanmencetakTidakiabetul."
91
Anda perlu berasumsi bahwa terdapat suatu metoda bernama raiseToPow yang mengambilduabilanganbulatsebagaiargumendanargumenkeduasebagaipangkat argumenpertama.Sebagaicontoh:
intx=raiseToPow(2,3);
akanmemasukkannilai8kedalamx,karena23=8
92
Jugaperhatikanbahwabaristerakhiradalahbentukalternatifdaripernyataanreturn yangjugaterdapatnilaiyangakandikembalikan.Pernyataantersebutberarti,kembali secepatnyadarimetodeinidangunakannilaiberikutsebagainilaikembalian.Nilai yangdisediakanbisalebihkompleks,jadikitabisamenulismetodelebihsingkat: publicstaticdoublearea(doubleradius){ returnMath.PI*radius*radius; } Dilainpihak,variabelsementarasepertiarealebihmembuatdebuggingjadilebih mudah.Padakeduakasus,tipenilaikembalianpadapernyataanreturnharussesuai dengantipekembalianmetode.Dengankatalain,ketikaandamendeklarasikanbahwa nilaikembalianadalahdouble,andamembuatjanjibahwametodeinibetulbetulakan menghasilkandouble.Jikaandamencobareturndengantanpanilai,ataunilaidengan nilaiyangberbeda,kompilerakanmemaksaandamengubahnya(menampilkan kesalahan).
94
Jikaandameletakkanstatemenreturndidalampercabangan,andaharusmenjamin bahwasetiapjalanyangmungkinpadaprogramakanmencapaistatemenreturn. Misalnya publicstaticdoubleabsoluteValue(doublex){ if(x<0){ returnx; }elseif(x>0){ returnx; }//WRONG!! } progamdiatastidaksahkarenajikaxsamadengan0,makatidakadakondisiyang benardanmetodeakankembalitanpamencapaistatemenreturn.Pesankompileruntuk halsepertiiniadalahreturnstatementrequiredinabsoluteValue,yangadalahpesan 95
memusingkanmengingattelahadaduastatemenreturn.
5.2PengembanganProgram
PadatitikiniandaseharusnyatelahbisauntukmelihatpadametodeJavayanglengkap danmelaporkanapayangmerekakerjakan.Tetapimungkinbelumjelasbagaimanacara menulisnya.Sayaakanmenyarankansatuteknikyangsayasebutincremental development.
Sebagaicontoh,bayangkanandainginmencarijarakantaraduatitik,dengankoordinat (x1,y1)dan(x2,y2).Denganrumusberikut
Langkahpertamaadalahmemikirkanbagaimanametodedistanceakanterlihatpada Java.Dengankatalainapasajainputdanapasajaoutputnya.
96
Langkahberikutpadapengembanganadalahmemangkatkandxdandy.Kitabisa menggunakanmetodeMath.pow,tetapiakanlebihmudahdancepatjikahany mengalikannyadengandirinyasendiri. publicstaticdoubledistance (doublex1,doubley1,doublex2,doubley2){ doubledx=x2x1; doubledy=y2y1; doubledsquared=dx*dx+dy*dy; System.out.println("dsquaredis"+dsquared); return0.0; } 98
Lagi,sayaakanmengkompilasidanmenjalankanprogrampadatahapinidanmengecek nilai(yangseharusnya25).
LangkahterakhiradalahmenggunakanMath.sqrtyaitumetodeuntukmenghitungdan mengembalikanhasil. publicstaticdoubledistance (doublex1,doubley1,doublex2,doubley2){ doubledx=x2x1; doubledy=y2y1; doubledsquared=dx*dx+dy*dy; doubleresult=Math.sqrt(dsquared); returnresult; } lalupadametodemain,kitalaluakanmengeceknilaidarihasilmetodediatas.
Halkuncipadaprosesadalah:
Gunakanvariabelsementarauntukmenyimpannilai(nilaiyangbukanhasil akhir)jadiandabisamencetakdanmengeceknya. 99
5.3Komposisi
Sepertiyangtelahandaketahui,ketikaandamendefinisikansebuahmetode,andabisa menggunakannyasebagaibagiandariekspresi,danandabisamembangunmetodebaru menggunakanmetodeyangtelahada.Misalnya,bagaimanajikaseseorangmemberikan andaduatitik,titikpusatdarilingkarandansebuahtitikdarikeliling,danbertanya tentangluaslingkaran.
Jikatitiktengahdisimpanpadavariabelxcdanyc,dantitikkelilingadalahxpdanyp. Langkahpertamaadalahmencarijarijarilingkaran,yangmerupakanjarakantaradua titik.Untungnya,kitamemilikisebuahmetode,distanceyangmelakukan: doubleradius=distance(xc,yc,xp,yp); Langkahkeduaadalahmencariluaslingkarandenganjarijariyangada,dan mengembalikannya doublearea=area(radius); returnarea; Denganmenggabungkansemuanyakedalamsebuahmetode,makakitadapatkan: publicstaticdoublefred (doublexc,doubleyc,doublexp,doubleyp){ doubleradius=distance(xc,yc,xp,yp); doublearea=area(radius); returnarea; 100
} Namametodeiniadalahfred,yangmungkinkelihatanganjil.Sayaakanmenjelaskan padabagianberikutnya.
Variabelsementararadiusdanareabergunauntukpengembangandandebugging,tetapi ketika program telah bekerja kita bisa membuat nya lebih singkat dengan menggabungkanpemanggilanmetode. publicstaticdoublefred (doublexc,doubleyc,doublexp,doubleyp){ returnarea(distance(xc,yc,xp,yp)); }
5.4Overloading
Padabagiansebelumnyaandamungkinmenyadaribahwafreddanareamelakukanhal yangsama,mencariluaslingkarantetapidenganduaparameteryangberbeda.Untuk area,kitaharusmenyediakanradius;untukfredkitaharusmenyediakanduatitik.
Jika kedua metode melakukan hal yang sama, merupakan hal yang lazim untuk memberikannamayangsama.Dengankatalain,akanlebihbaikjika fred bernama area. Memilikilebihdarisatumetodedengannamayangsama,yangdisebut overloading, adalahsahdalamJava.Jadikitabisamenamaifreddengan: publicstaticdoublearea(doublex1,doubley1,doublex2,doubley2){ } 101 returnarea(distance(xc,yc,xp,yp));
Ketikaandamemanggilmetodeyangdioverloading,Javamengetahuiversiyangmana yang anda inginkan dengan melihat pada argumen yang anda sediakan. Jika anda menulis doublex=area(3.0); Java akan mencari metode yang bernama area yang menggunakan satu parameter double sebagai argumen, jadi ia akan menggunakan versi yang pertama. Yang mengartikanargumensebagairadius.Jikaandamenulis: doublex=area(1.0,2.0,4.0,6.0); MakaJavaakanmenggunakanversiyangkedua.
Sebenarnya.Halinimengingatkansayasalahsatuaturandaridebugging: yakinkan bahwa versi program yang anda perbaiki adalah versi program yang sedang berjalan! Kadangkadang anda mungkin menemukan diri anda membuat perubahan setelahperubahanyanglainpadasuatuprogram,danmelihathalyangsamasetiapkali anda menjalankannya. Ini adalah tanda peringatan untuk satu alasan atau yang lain bahwa anda tidak menjalankan versi program yang sedang anda perbaiki. Untuk 102
mengeceknya, letakkan print (tidak menjadi masalah apa yang anda cetak) dan yakinkanbahwaprogrammencetakpernyataanprinttersebut.
5.5EkspresiBoolean
Sebagianbesaroperasiyangtelahkitalihatmenghasilkannilaidengantipeyangsama denganoperannya.Misalnya+operatormengambilduaintdanmenghasilkansebuah intatauduadoubleyangmenghasilkansebuahdouble.
Ekspresibooleandanvariabelbekerjasepertihalnyatipeyanglain: booleanfred; fred=true; booleantestResult=false; Contoh pertama adalah deklarasi variabel sederhana; contoh kedua adalah sebuah penugasan, dancontoh ketigaadalah kombinasidari deklarasidan penugasan, yang kadangkadangdisebutinisialisasi.NilaitruedanfalseadalahkatakuncidalamJava, jadimerekamungkintampildenganwarnayangberbeda,tergantungpadalingkungan pengembangananda.
booleanpositiveFlag=(x>0);//trueifxispositive danmenggunakannyasebagaibagiandaripernyataankondisional: if(evenFlag){ System.out.println("nwasevenwhenIcheckedit"); } Variabel yang digunakan pada cara ini sering disebut sebagai flag, karena ia menunjukkanadaatautidakadanyasuatukondisi.
5.6OperatorLogika
AdatigaoperatotlogikapadaJava:AND,OR,NOT,yangmemilikisimbol&&,||, dan !. Sematik (arti)dari operator operatorini sama dengan artinya dalam bahasa Inggris.Misalnyax>0d&&x<10berartibenarhanyajikaxlebihbesardari0danlebih kecildari10.
Operatorlogikaseringmenyediakancarauntukmenyederhanakanpernyataankondisi bersarang.Misalnya bagaimana anda menuliskode di bawahini menggunakansatu kondisional. if(x>0){ if(x<10){ System.out.println("xisapositivesingledigit."); 104
} }
5.7MetodeBoolean
Metodedapatmengembalikannilaibooleansepertihalnyatipeyanglain,yangsering menyembunnyikanpengetesankompleksdidalammetode.Misalnya publicstaticbooleanisSingleDigit(intx){ if(x>=0&&x<10){ returntrue; }else{ returnfalse; } } Nama metodeadalah isSingleDigit. Cara yangumumuntuk memberi namametode booleansepertipertanyaanya/tidak(yes/noquestion).Tipekembalianadalahboolean yangberartisetiappernyataankembalianharusmenyediakanekspresiboolean.
booleanbigFlag=!isSingleDigit(17); System.out.println(isSingleDigit(2)); BarispertamamenugaskannilaitruepadabigFlagdenganalasan17bukanangkasatu digit. Bariskeduamencetak true karena2adalahbilangansatudigit.Benarbahwa printlndioverloadinguntukjugamenanganiboolean. Cara yang paling umum untuk menggunakan metode boolean adalah di dalam pernyataankondisional if(isSingleDigit(x)){ System.out.println("xislittle"); }else{ System.out.println("xisbig"); }
5.8LagitentangRekursi
Sekarangkitamemilikimetodeyangmengembalikannilai,andamungkintertarikuntuk mengetahuibahwakitatelahmemilikibahasapemrogramanyanglengkap,yangsaya maksudkanbahwasegalahalyangdapatdihitungdapatdiekspresikandalambahasaini. Semuaprogramyangtelahditulisdapatdituliskembalimenggunakanfiturfiturbahasa yang telah kita gunakan sejauh ini (sebenarnya, kita juga membutuhkan beberapa perintahuntukmengontrolalatsepertikeyboard,mouse,dandiks).
Membuktikan klaim ini bukanlah pekerjaan yang mudah . Hal ini pertama kali diselesaikanolehAlanTuring,salahsatu computerscientisct pertama(beberapaorang akan beargumen bahwa ia adalah seorang matematikawan, tetapi banyak computer scientistyangmemulaisebagaimatematikawan).HalinidisebursebagaithesisTuring. 106
Jikaandabelajartentangteorikomputasiandaakanmemilikikesempatanuntukmelihat pembuktianini.
Untukmemberikanandaideapayangbisaandalakukandenganalatyangtelahkita pelajarisejauhini,marikitamelihatpadabeberapametodeuntukmengevaluasidefinisi fungsi rekursif matematika. Definisi rekursif sama dengan definisi melingkar, yaitu definisiyangberisiapayangdidefinisikan.
Jika anda bisa menulis definisi rekursif dari sesuatu, anda biasanya dapat menulis program Java untuk menghitungnya. Langkah pertama adalah untuk membuktikan parameterapayangakandimilikifungsitersebut,danapanilaikembaliannya.Dengan sedikit pemikiran, anda bisa menyimpulkan bahwa faktorial menggunakan bilangan bulatsebagaiparameterdanjugamengembalikanbilanganbulat: publicstaticintfactorial(intn){ } Jikaargumensamadengan0,makaakanmengembalikan1:
107
publicstaticintfactorial(intn){ if(n==0){ return1; } } Jikatidak,iniadalahbagianyangmenarik,kitaharusmembuatpemanggilanrekursif untukmencarinilaifaktorialn1,dankemudianmengalikannyadengann. publicstaticintfactorial(intn){ if(n==0){ return1; }else{ intrecurse=factorial(n1); intresult=n*recurse; returnresult; } } Jikakitamelihatpadaaliraneksekusipadaprogram,makaakanserupadenganmetode nLinespadababsebelumnya,jikakitamemanggilfaktorialdengannilai3: Karena3tidaksamadengan0,kitamengambilcabangkeduadanmenghitungfaktorial darin1.... Karena 2 tidak sama dengan 0, kita mengambil cabang kedua dan menghitungfaktorialdarin1.... Karena1tidaksamadengan0,kitamengambilcabang keduadanmenghitungfaktorialdarin1....
108
Berikutinidiagramstackuntukurutanpemanggilanfungsidiatas: Nilaikembalinadipelihatkandilewatkankembalipadastack.
Perhatikan bahwa pada instance terakhir dari faktorial, variabel lokal recurse dan resulttidakadakarenaketikan=0cabangyangmenciptakanmerekatidakdieksekusi.
5.9Leapoffaith
Mengikuti aliran eksekusi adalah salah satu cara untuk membaca program, tetapi
109
sebagaimanatelahandalihatpadabagiansebelumnya,haliniakansulituntukbeberapa jenisprogram.Sebagaialternatifkitabisamenggunakancaraleapoffaith.Ketika anda melihat pemanggilan metode, sebagai ganti mengikuti aliran eksekusi, anda mengasumsikanbahwametodebekerjadenganbenardanmengembalikannilaiyang cocok.
Sebenarnya, anda telah mempraktekkan leap of faith ketika anda menggunakan metode bawaan. Ketika anda menggunakan metode Math.cos atau drawOval. Anda tidakperdulidenganimplementasimetodeini.Andahanyaberasumsibahwametodeini bekerja,karenaorangyangmenulismetodeiniadalahprogrammeryangbaik.Ketika kitatelahyakinbahwametodeinibenardenganmencobadanmengujikodekitabisa menggunakanmetodeinitanpamelihatkodeitukembali.
Hal yang sama berlaku ketika anda memanggil salah satu metode kepunyaan anda. Misalnyapadabagian5.7kitamenulismetodeisSingleDigityangmenghitungapakah sebuahbilanganadadiantara0dan9.
Halyangsamdenganprogramrekursif.Ketikaandamelihatpadapemanggilanrekursif. Sebagaigantimelihatpadaaliranprogram,andaharusberasumsibahwapemanggilan rekursifbekerjadenganbaik(menghasilkannilaiyangbenar),danlalutanyakanpada diri anda, Asumsikan bahwa saya bisa mencari faktorial n1, dapatkah saya menghitungfaktorialn?Padakasusini,jelasbahwaandabisa,denganmengalikannya dengann.
offaith
5.10SatuContohLagi
Pada contoh sebelumnya saya menggunakan variabel sementara untuk mengetahui langkah, dan untuk membuat kode lebih mudah untuk didebug, tetapi saya bisa menghematbeberapabaris: publicstaticintfactorial(intn){ if(n==0){ return1; }else{ returnn*factorial(n1); } } Dari sekarang saya akan menggunakan versi yang lebih singkat, tetapi saya merekomendasikan anda untuk menggunakan versi yang lebih eksplisit ketika mengembangkan kode. Ketika anda telah membuat nya bekerja, anda bisa menciutkannya
Setelah faktorial, contoh klasik tentang definisi rekursif fungsi matematika adalah fibonacci.Yangmemilikidefinisiberikut: fibonacci(0)=1 fibonacci(1)=1 fibonacci(n)=fibonacci(n1)+fibonacci(n2); DiterjemahkankeJavasehinggamenjadi publicstaticintfibonacci(intn){ 111
if(n==0||n==1){ return1; }else{ returnfibonacci(n1)+fibonacci(n2); } } Jikaandamencobauntukmengikutialiraneksekusi,bahkandengannilaiyangkecil, kepalaandaakanmeledak.Tetapimenurutprinsipleapoffaith,jikakitaberasumsi bahwaduapemanggilanrekursif(ya,andabisamelakukanduapemanggilanrekursif) bekerja dengan benar, maka dengan jelas kita bisa mendapatakan hasil yang benar denganmenambahkankeduanya.
5.11DaftarKata
returntype:Bagiandeklarasimetodeyangmenunjukkannilaidengantipeapa yang akandikembalikan returnvalue:Nilaiyangdisediakansebagaihasildaripemanggilanmetode. deadcode:Bagianprogramyangtidakakanpernahdieksekusi,seringterjadi arena diletakkansetelahreturn scaffolding : kode yang digunakan selama pengembangan program tetapi bukan merupakanbagiandariversiakhir void : tipe Kembalian khusu yang menunjukkan metode void; yaitu metode yang tidakmengembalikannilai. overloading : Memiliki lebih dari satu metode dengan nama yang sama tetapi parameteryangberbeda.Ketikaandamemanggilmetodeyang dioverloading. Javamengetahuiversimanayangdigunakandengan melihat pada argumen yang 112
andasediakan boolean:Tipevariabelyanghanyabisaberisiduanilaitruedanfalse operatorkondisional:operatoryangmembandingkanduanilaidan nilaibooleanyangmenunjukkanhubunganantarakedua operan. Operatorlogika:operatoryangmenggunakannilaibooleandanmenghasilkan nilai boolean. Inisialisasi : pernyataan yang mendeklarsikan variabel baru dan menugaskan nilai kedalamnyapadawaktuyangsama. menghasilkan
5.12Latihan
latihan5.1 TulissebuahmetodeyangbernamisDivisibleyangmengambilduabilanganbulatndan mmengembalikannilaitruejikanhabisdibagimdanfalsejikatidak. Latihan5.2 apakahkeluarandariprogramberikut?Tujuandarilatihaniniadalahuntukmelatih andamengertitentangoperatorlogikadanaliraneksekusipadametode. publicstaticvoidmain(String[]args){ booleanflag1=isHoopy(202); booleanflag2=isFrabjuous(202); System.out.println(flag1); System.out.println(flag2); if(flag1&&flag2){ System.out.println("ping!"); } if(flag1||flag2){ 113
System.out.println("pong!"); } } publicstaticbooleanisHoopy(intx){ booleanhoopyFlag; if(x%2==0){ hoopyFlag=true; }else{ hoopyFlag=false; } returnhoopyFlag; } publicstaticbooleanisFrabjuous(intx){ booleanfrabjuousFlag; if(x>0){ frabjuousFlag=true; }else{ frabjuousFlag=false; } returnfrabjuousFlag; } latihan5.3 Jarakantaraduatitik(x1,y1)dan(x2,y2)adalah
114
Latihan5.4 Tujuandarilatihaniniadalahuntukmempraktekkansintaksdarifruitfulmethods a) Cari solusi anda sendiri untuk latihan 3.5 dan pastikan anda masih bisa mengkompilasidanmenjalankannya. b) Ubahlahmultaddmenjadimetodeyangmengembalikannilai,jadisebagaiganti mencetakhasilnya,iaakanmengembalikannya. c) Dimanasajadidalamprogrammultadddipanggil,gantipemanggilannyajadi iamenyimpanhasilnyadalamvariabeldan/ataumencetakhasil d) Ubahjugayikesdengancarayangsama. Latihan5.5 Tujuan dari latihan ini adalah untuk menggunakan diagram stack untuk mengerti tentangpengeksekusiandariprogramrekursif. publicclassProd{
115
publicstaticvoidmain(String[]args){ System.out.println(prod(1,4)); } publicstaticintprod(intm,intn){ if(m==n){ returnn; }else{ intrecurse=prod(m,n1); intresult=n*recurse; returnresult; } } } a.gambardiagramstackyangmenunjukkankeadaanprogramsesaatsebeluminstance terakhirprodselesai.Apakahkeluarandariprogram? b.Jelaskandenganbeberapakataapayangsebenaranyadilakukanprod. c.tuliskembaliprodtanpamenggunakanvariabelsementararecursedanresult.
116
Tulismetodebernamaackyangmengambilduaintsebagaiparameter,menghitungdan mengembalikannilaidarifungsiAckerman.
Peringatan:nilaikeluaranakanbertambahbesardengancepat.Andaharusmencobanya untuknilaimdann(tidaklebihdari2). Latihan5.7 a.BuatprogrambernamaRecurse.javadantulismetodemetodeberikut: //first:kembalikankarakterpertamadariStringyangdiberikan publicstaticcharfirst(Strings){ returns.charAt(0); } //last:kembalikanStringbaruyangberisisemuakecualihurufpertamadari //Stringyangdiberikan publicstaticStringrest(Strings){ returns.substring(1,s.length()); } //length:kembalikanpanjangdaristringyangdiberikan publicstaticintlength(Strings){ returns.length(); } b.Tulisbeberapkodepadamainyangmengetessetiapmetodemetodeini.Andaharus
117
yakinbahwamerekabisabekerjadenganbaikdanandabisamengertiapayangmereka kerjakan. c.Tulismetodeyangbernama printString yangmengambilStringsebagaiparameter danmencetakhurufhurufdariStringtersebutsatusetiapbaris.Metodeiniharuslah merupakanmetodevoid. d.Tulismetodeyangbernama reverseString yangmengambilsebuahStringsebagai parameterdanmengembalikanStringbaru.Stringyangbaruharusberisihurufhuruf yangsamadenganparameternyatetapidenganurutanyangterbalik.Misalnyakeluaran kodedibawah Stringbackwards=reverseString("AllenDowney"); System.out.println(backwards); adalah yenwoDnellA Latihan5.8 a.BuatprogrambernamaSum.javatulisduametodedibawah publicstaticintmethOne(intm,intn){ if(m==n){ returnn; }else{ returnm+methOne(m+1,n); } } publicstaticintmethTwo(intm,intn){ if(m==n){
118
returnn; }else{ returnn*methTwo(m,n1); } b.Tulisbeberapabarispadamainuntujmengujimetodemetodeini.Panggilmereka beberapakalidengannilaiyangberbedamdanlihatapayangandadapatkan.Dengan beberapakombinasidaripengetesan,caritahuapayangdilakukanmetodeinidanberi merekanamayangsesuai.Tambahkankomentaryangmenjelaskanfungsinya c. Tambahkan pernyataan println pada awal metode sehingga mereka mencetak argumensetiapkalidipanggil.Teknikinibergunauntukmendebugprogramrekursif, karenaiamendemontrasikanaliraneksekusi.
Latihan5.9 Tulismetoderekursifbernamapoweryangmengambildoublexdansebuahintegern dan mengembalikan xn.. Petunjuk: definisi rekursif dari power(x,n)=x*power(x,n10, jugaingatbahwaapapunyangdipengkatkan0adalah1.
Latihan5.10 (latihaniniberdasarkanpadahalaman44bukuStructureandIntepetationofComputer ProgramskaranganAbelsondanSussman) Algoritma berikut dikenal sebagai algoritma Euclid. Algoirtma ini berdasarkan dari observasi bahwa, jika r adalah sisa ketika a dibagi dengan b maka faktor pembagi terbesar(fpb)dariadanbsamadenganfaktorpembesardaribdanr.sehinggabisa dinyatakandenganpersamaan gcd(a,b)=gcd(b.r)
119
Yang sukses untuk mengurangi masalah penghitungan GCD ( Greatest Common Divisor)contohpenerapanalgoritma, gcd(36,20)=gcd(20,16)=gcd(16,4)=gcd(4,0)=4 YangmenghasilkanGCDdari36dan20adalah4.Dapatdiperlihatkanbahwauntuk berapapunangkaawal,penguranganberulangmenghasilkanpasangandimanabilangan yangkeduaadalah0.danGCDadalahnomoryanglainpadapasanganitu. Tulissebuahmetodebernamagcdyangmengambilduaparameterbilanganbulatdan menggunakan algoritma Euclid untuk menghitung dan mengembalikan greatest commondivisor(gcd)/FaktorPersekutuanTerbesar(FPB)darikeduabilangan.
120
Saya belum pernah mengatakan hal ini sebelumnya, tapi adalah sesuatu yang legal dalam Java untuk membuat lebih dari satu assignment terhadap satu variabel yang sama. Akibat yang akan timbul dengan adanya assignment berganda ini adalah terjadinyapenggantiannilailamadarisuatuvariabeldengannilaiyangbaru. Perhatikancontohberikutini: intfred=5; System.out.print(fred); fred=7; System.out.println(fred); Output dari program ini adalah 57. Kok bisa? Ini terjadi karena pada kesempatan pertama kita mencetak nilai 5 menggunakan metode print sedangkan pada kesempatanberikutnyakitamencetaknilai7menggunakanmetodeprintln . Karenasifat multiple assigment inilahsayamendeksripsikanbahwavariabelvariabel dalamJavamerupakanpenampung(container)untuknilainilai.KetikaAndamemberi (assign) sebuahnilaiuntuksuatuvariabel,Andaberartimengubahisidari container tersebut,perhatikangambardibawahini: intfred=5; fred=7; fred fred 5 57
Ketika terjadi multiple assignment terhadap suatu variabel, adalah penting untuk 121
membedakanantarasebuahpernyataanassignmentdengansebuahpernyataanequality (kesamaan). Karena Java menggunakan simbol = sebagai simbol assignment, terkadangkitaseringtergodauntukmenganggappernyataansepertia = b sebagai pernyataanequality.Padahalbukan! Untuk memperjelas masalah ini, simaklah beberapa sifat berikut: equality bersifat komutatif,sementaraassignmenttidak.Sebagaicontoh,dalamlingkunganmatematika; jika a = 7 maka 7 = a.NamuntidakdalamlingkunganJava!Jika a = 7; merupakan pernyataan yang legal maka pernyataan sebaliknya, yaitu 7 = a; tidaklahdemikian. Lebih jauh lagi, dalam matematika, sebuah pernyataan yang bersifat equality akan selalubenaruntukselamanya.Sebagaicontoh,jikaa = bsekarang,maka a akan selalu sama dengan b. Dalam Java, sebuah pernyataan assignment memang dapat membuatduavariabelbernilaisama,tapikeadaannyatidakakansamadenganapayang telahterjadidalamduniamatematika. inta=5; intb=a; a=3; //adanbsekarangsama
//adanbsekarangtidaklagisama
Baris terakhir kode di atas memang mengubah nilai variabel a, tapi tidak dengan variabel b.Nilai b masihtetapsamadengannilaivariabel a yangpertama,yaitu 5. Dalam lingkungan bahasa pemrograman lain, sebuah simbol alternatif lain sering digunakansebagaisimbolpernyataanassignment.Misalnya:< atau":= ". Halinidilakukansebagailangkahantisipasiuntukmencegahkerancuan. Meskipun multiple assignment seringkali berguna, Anda harus tetap hatihati dalam menggunakannya.Jikanilaidarisuatuvariabelselaluberubahubahpadalokasi/bagian yang berbedabeda di dalam program, maka Anda akan menemui kesulitan ketika hendakmendebugdanmembacakodenya. 122
6.2
Iterasi
Salah satu fungsi komputer yang paling sering dimanfaatkan manusia adalah untuk melakukansesuatu(baca:tugas)yangsifatnyaberulangulang.Mengulangulangtugas yangsamaatauidentiktanpamelakukansatukesalahanpunadalahsesuatuyangdapat dikerjakandengansangatbaikolehkomputer,tapitidakolehmanusia. Kita telah melihat programprogram yang menggunakan teknik rekursi untuk melakukan perulangan, seperti nLines dan countdown . Bentuk perulangan sepertiinilahyangdisebutdenganiterasi,danJavamenyediakanbeberapafiturbahasa yangdapatmemudahkankitauntukmembuatprogramprogramyangiteratif. Duafituryangakankitalihatpertamaadalahpernyataanwhiledanpernyataanfor .
6.3
PernyataanWhile
Dengan pernyataan while ,kitadapat menulisulang countdown dengancara sebagaiberikut: publicstaticvoidcountdown(intn) { while(n>0) { System.out.println(n); n=n1; } System.out.println("Blastoff!"); } Andadapatmenulispernyataan while inilaiknyamenuliskalimatdalamBahasa Inggris.Maksudnya,kodediatasdapatdibacadengankalimatsepertiini,"Whilenis 123
greaterthanzero,continueprintingthevalueofnandthenreducingthevalueofnby1. When you get to zero, print the word Blastoff!". Dalam Bahasa Indonesia berarti kalimatnyaakanmenjadisepertiini,"Selamanmasihlebihbesardaripada0,teruslah mencetaknilain,kemudiankuranginilaindengan1.KetikaAndasudahsampaipada nilai0,cetaklahkataBlastoff!". Untuklebihjelasnya,berikutinimerupakanalureksekusiyangterjadidalamkodedi atas: 1. Cek/Evaluasi syarat (condition) yang berada dalam tanda kurung, apakah bernilaitrue ataufalse . 2. Jikasyaratitubernilai false ,Javaakankeluar(exit)daripernyataanwhile tersebutlalumelanjutkaneksekusikepernyataanselanjutnya. 3. Jikasyarattersebutbernilai true ,Javaakanmengeksekusisetiappernyataan yangberadadalamkurungkurawal,lalukembalikelangkahnomor1. Bentuk aliran program seperti inilah yang disebut loop (baca: putaran atau siklus). Disebutdemikiankarenapernyataanpadalangkahyangketigaakanmembuatprogram kembali lagi ke bagian atas dari program itu sendiri. Perhatikan bahwa jika syarat langsungbernilaifalse padasaatmasukkedalamloop,pernyataanyangberadadi dalam loop tersebut tidak akan dieksekusi. Pernyataan yang berada di dalam loop biasanyadisebutbody(badan)dariloop. Badan loop harus merubah nilai dari satu atau lebih variabel sehingga syarat yang dievaluasiakansampaipadanilaifalse danlooppunakanberakhir.Jikatidak,loop tersebut akan melakukan putaran eksekusi selamanya. Keadaan inilah yang disebut denganinfiniteloop(baca:putarantanpabatas).Contohinfiniteloopdalamkehidupan seharihariyangmungkinseringkitaditemuiadalahinstruksidalamkemasanshampoo, "CucirambutAnda,bilasdenganair,laluulangi."
124
Dalamkasuscountdown ,kitadapatmembuktikanbahwalooppastiakandihentikan karenakitatahubahwanilaidarivariabeln adalahnilaiyangterbatas(finite).Disitu kitadapatmelihatbahwanilain akansemakinmengecilsetiapkalimelewatiloop(tiap iterasi).Keadaaninitentuakanmembawakitakepadanilai n yangsamadengan0. Namun dalam kasuskasus loop lainnya, terkadang tidaklah mudah untuk mengatakannya.Perhatikancontohberikutini: publicstaticvoidsequence(intn){ while(n!=1){ System.out.println(n); if(n%2==0){ n=n/2; }else{ n=n*3+1; } } } Syaratloopdiatasadalahn != 1,jadiloopakanterusdiprosessampainilaivariabel n=1 .Kondisiiniakanmenyebabkansyaratbernilaifalse . Dalam tiap iterasinya, program akan mencetak nilai dari n sekaligus memeriksa apakahnilain tersebuttermasukgenapatauganjil.Jikantermasukgenap,makanilai n akandibagidengan2.Tapijikatermasukganjil,makanilain akandigantidengan nilaidarin*3 + 1.Sebagaicontoh,jikanilaiawal(argumenyangdilewatkandalam metodesequence )samadengan3,makahasilyangakandicetakadalah3, 10, 5,16,8,4,2. Karena nilai n kadang bertambah dan kadang menurun, tidak ada bukti yang kuat bahwanakansamadengan1,ataudengankatalainagarprosesdalamprogramdapat 125 //nisodd //niseven
dihentikan. Untuk beberapa nilai n, kita dapat membuktikan bahwa terminasi (penghentian) terhadap programakan terjadi. Sebagai contoh, jikanilai awal dari metodetersebutadalahbilanganyangtermasukkelipatan2,makanilain akanselalu genapsetiapkalimelintasiloop,sampaikitasampaikenilai n = 1.Dalamcontoh sebelumnyakitadapatmelihatmanakalanilain telahsamadengan16 makanilain berikutnyapastiakanmembawavariabel n ke 1 (16, 8, 4, 2, 1).catatan: angka1 tidakdicetakdalamoutput. Nilainilailain(selainkelipatan2)tentunyatidakdapatdimasukkankedalambentuk umum seperti di atas. Pertanyaan menariknya adalah; dapatkah kita membuktikan bahwaprogramdiataspastiakandapatdihentikan(terminate)untuksemuanilai n? Sampaisejauhini,belumadayangdapatmembuktikankebenaranpertanyaandiatas!
6.4
Tabel
Salah satu manfaat loop yang paling baik adalah untuk membuat (generate) dan mencetaktabeldata.Sebagaicontoh,sebelumkomputerdapatdigunakansebaikseperti sekarang,orangorangharusmenghitunglogaritma,sinus,cosinus,sertafungsifungsi matematikalainnyamenggunakantangan(baca:manual). Untukmembuatpekerjaanpekerjaandiatasmenjadilebihmudah,dibuatlahbeberapa bukuyangberisitabeltabelpanjangyangdapatmembantukitauntukmelihatnilainilai daribeberapafungsi.Untukmembuattabeltabelinidibutuhkanwaktuyanglama.Dan membosankan! Akibatnya, hasilnya pun terkadang akan dipenuhi banyak error (kesalahan). Ketikakomputertelahmunculbesertamonitornya,salahsatureaksiawalyangmuncul adalah, "Hebat! Kita dapat menggunakan komputer untuk membuat tabel tabel, sehinggatidakakanadakesalahanlagi".Euforiainisecaraumummemangakhirnya terbukti,tapiinihanyalahsecuilkemampuansajadaribegitubanyakhalyangdapat 126
dilakukan dengan komputer. Setelah komputer (juga kalkulator digital) digunakan secaraluasolehbanyakkalangan,tabeltabeltersebutmenjadibarangkuno. Setidaknyabisadikatakanhampirdemikian.Karenauntukbeberapaoperasi,komputer juga masihmenggunakantabeltabeluntukmelihat jawabanyangpalingmendekati, untukkemudiankembalilagimenggunakankomputerketikahendakmemperbaikinilai pendekatantersebut.Dalambeberapakasus,pernahterjadikesalahanfataldalamtabel tabel yang dibuat menggunakan komputer. Kasus populer menyangkut ini adalah kesalahanprosessorIntelPentiumgenerasiawaldalammelakukanoperasipembagian (division)untuknilaifloatingpoint. Meskipunsebuah"tabellogaritma"tidaklahterlalupentinglagisepertibeberapatahun yanglalu,tapikitamasihdapat menggunakannyasebagaicontohyangbagus untuk menunjukkanbagaimanacaraiterasibekerja.Programberikutiniakanmencetakurutan nilainilaidikolombagiankiridanlogaritmanyadikolombagiankanan: doublex=1.0; while(x<10.0){ System.out.println(x+""+Math.log(x)); x=x+1.0; }
8.02.0794415416798357 9.02.1972245773362196 Denganmelihatnilainilaidiatas,bisakahAndamemberitahudefaultnilaibasisdari fungsilogyangdigunakanolehJava? Karenanilaikelipatan2memilikiperanyangpentingdalamilmukomputer,terkadang kitainginmenemukanlogaritmadengannilaibasis2.Untukmenemukannya,kitabisa menggunakanformulaberikutini: log 2 x=log e x/log e 2 Ubahlahpernyataanprint dalamkodediatassehinggamenjadisepertiberikutini:
System.out Math.log(x)/M .print ln(x +"" + ath.lo g(2.0) );
pernyataandiatasakanmenghasilkan: 1.00.0 2.01.0 3.01.5849625007211563 4.02.0 5.02.321928094887362 6.02.584962500721156 7.02.807354922057604 8.03.0 9.03.1699250014423126
Darihasildiataskitadapatmelihatbahwa1,2,4,dan8merupakanbilangankelipatan 2.Inikarenalogaritmamerekayangberbasis2menghasilkanbilangandengannilai pembulatan (rounded). Jika kita ingin menemukan logaritma dari bilanganbilangan lainnyaselain2,kitadapatmemodifikasiprogramtersebutdengancarasepertidibawah 128
ini;
double x= 1.0; while (x< 100.0) { System.out.p Math.log(2.0) x= x*2.0; } rintln (x +"" +Math.log(x) ); /
Ketimbangselalumenambahkansesuatukevariabelx setiapkalimelewatiloopyang akanmenghasilkanderetaritmatika,sekarangkitaakanmengalikanvariabelxdengan sesuatusehinggamenghasilkanderetgeometri.Berikutinimerupakanhasildarikode diatas: 1.00.0 2.01.0 4.02.0 8.03.0 16.04.0 32.05.0 64.06.0
Tabellogaritmamungkinsudahtidakterlalubergunauntuksaatini,tapiuntukseorang ilmuwankomputer(computerscientist),mengetahuibilangankelipatan2ataupangkat2 adalah wajib! Jika kamu sedang dalam keadaan idle (baca: malas atau bete), berusahalah utuk mengingat bahwa bilangan berpangkat atau kelipatan 2 dalam komputerhanyaakansampaipadaangka65536(iniadalahhasildari216).
6.5
TabelDuaDimensi
Sebuahtabelberdimensiduaadalahsebuahtabelyangdidalamnyaterdapatnilainilai 129
yangberadadalamperpotongan(interseksi)antarasatubarisdansatukolom.Contoh yang baik untuk memperlihatkan tabel ini adalah tabel perkalian (multiplication). AnggapsajaAndainginmencetaktabelperkalianuntuknilai1sampaidengan6. Carayangbagusuntukmemulaiyaadalahdenganmenulissebuahloopsederhanayang mencetakkelipatan2,semuadalam1baris. inti=1; while(i<=6){ System.out.print(2*i+""); i=i+1; } System.out.println(""); Baris pertamamenginisialisasi sebuahvariabel,yakni i.Variabeliniakanbertugas sebagaicounter,atauvariabeluntukmelakukanloop.Ketikaloopdieksekusi,nilaidari iakanterusnaikmulaidari1hingga6.Ketikaisamadengan7,loopakandihentikan. Setiap melewati loop, kita mencetak nilai dari 2 * i diikuti dengan tiga spasi. Karena kita menggunakan perintah print ketimbang println , semua output akandicetakdalamsatubarisyangsama. Seperti yang sudah saya singgung dalam bagian 2.4, dalam beberapa lingkungan pemrograman, output dari perintah print akan terus disimpan dalam memori sampaiperintah println dipanggil.Jikaprogramsudahberhenti,tapiAndalupa memanggilperintah println ,Andamungkintidakakanpernahmelihatnilaiyang disimpantersebut. Outputdariprogramdiiniadalah: 24681012 So far, so good. Tahap berikutnya adalah membuat suatu bentuk enkapsulasi dan
130
generalisasi.
6.6
EnkapsulasidanGeneralisasi
Enkapsulasi(encapsulation)berartimengambilbeberapabagiandarikodeyangsudah ditulis untuk kemudian mengemasnya (wrapitup) dalam sebuah metode. Kita sebelumnyasudahmelihatduacontohenkapsulasi.Pertama,ketikakitamenulismetode printParity dalambagian4.3danisSingleDigit dalambagian5.7.
Generalisasiberartimengambilsatuhalyangspesifikdarisuatubagiankodedalam metode,misalnyamencetakkelipatan2,untukkemudianmembuatnyamenjadilebih umum. Dalam kasus ini berarti dengan cara membuat kode tersebut agar dapat mencetaknilaikelipatandarin. publicstaticvoidprintMultiples(intn){ inti=1; while(i<=6){ System.out.print(n*i+""); i=i+1; } System.out.println(""); }
Untukmengenkapsulasi,yangsayalakukanhanyalahmenambahsesuatudalambaris pertama. Dalam hal ini saya menambahkan nama metode, parameter, dan tipe pengembalian. Sedangkan untuk menggeneralisasi, yang saya lakukan adalah menggantinilai2denganparametern. Jikasayamemanggilmetodeinidenganargumen2makasayaakanmendapatkanhasil yangsamadenganprogramsebelumnya.Denganargumen3,hasilyangakankitalihat
131
adalahsebagaiberikut: 369121518 dandenganargumen4,outputnyaadalahsebagaiberikut: 4812162024 Mulai sekarang, Anda mungkin sudah dapat menerka bagaimana cara kita untuk membuat tabel perkalian: kita akan memanggil printMultiples secara
berulangulangdenganargumenyangberbedabeda.Tidakhanyaitu,disinikitajuga akanmenggunakanloopyangberbedauntukmelakukaniterasikedalambarisbaris tersebut. inti=1; while(i<=6){ printMultiples(i); i=i+1; } Pertamatama,perhatikanbetapamiripnyaloopinidenganyangberadadalammetode printMultiples . Saya hanya mengganti perintah print dengan sebuah
Bagaimana?Tampaksepertitabelperkalianbukan?Meskipunbentuknyajugakelihatan 132
agakagakmiringsedikit.JikabentukbentuksepertiinimenggangguAnda,Javatelah menyediakan metodemetode yang dapat memberi Anda kendali lebih baik atas masalahmasalahoutput,tapisayabelummaubertamasyakesanasekarang.Tungguya!
6.7
Metode
Dengan memberi sebuah nama untuk satu set perintahperintah/pernyataan tertentu,AndatelahmembuatprogramAndasemakinmudahuntukdibacadan diperiksa(debug).
Memecah program Anda yang panjang ke dalam beberapa metode dapat memudahkan Anda untuk membaginya ke dalam beberapa bagian terpisah. Dengan keadaan seperti ini, Anda dapat memeriksa bagianbagian tersebut dalamlingkunganyangterisolir(bebasdaribagianlainnya).Untukkemudian merangkainyakembalidalamprogram"besar"yangAndainginkan.
Metodedapatmemfasilitasirekursisekaligusiterasi. Metode yang dirancang dengan sangat baik biasanya dapat digunakan oleh programprogramlainnya.SekalisajaAndamampumenulisdanmemeriksanya denganbaik,otomatisAndaakandapatmenggunakannyakembali.
6.8
Enkapsulasi....sekalilagi!
inti=1; while(i<=6){ printMultiples(i); i=i+1; } } Proses yang sedang saya demonstrasikan adalah sebuah strategi pengembangan (developmentplan)yangumumdigunakan.Andamengembangkansuatukodesecara bertahap dengan cara menambah beberapa baris dalam bagian main atau bagian lainnya, lalu ketika Anda tahu bahwa proses ini bekerja dengan baik, Anda lalu mengambildanmemasukkannyakedalamsebuahmetode. AlasanmengapacarainibermanfaatuntukAndaadalahkarenaterkadangAndatidak mengetahuisecarapastikapanAndaakanmembagiprogramAndasecaraterpisahke dalam beberapa metode sekaligus. Pendekatan dengan model seperti ini dapat memudahkanAndauntukmelakukanprosesperancanganyangberiring/berbarengan denganprosespembuatanprogram.
6.9
VariabelLokal
Saatini,mungkinAndasedangkebingunganmemikirkantentangbagaimanasebuah variabel yang sama, yakni i, dapat digunakan oleh dua metode yang berhubungan sekaligus pada saat yang bersamaan (printMultiples printMultTable dan
).Bukankahsebelumnyasayatidakpernahmengatakankepada
AndabahwaAndahanyadapatmendeklarasikansebuahvariabelsatukalisaja?Dan tidakkahhalyangdemikiandapatmenimbulkanmasalahketikasalahsatudarimetode tersebut mengganti nilai dari variabel miliknya yang kita permasalahkan tersebut?
134
yangtidaksama.Merekamemangmempunyaiduanamayangsama,tapimerekatidak mengacukepadasatulokasipenyimpananyangsama.Olehkarenaitulah,mengubah nilaisalahsatudarimerekatidakakanmemberipengaruhapapunkepadanilaiyang lainnya. Variabelvariabelyangdideklarasikandidalamsebuahmetodedisebut variabellokal karena mereka terlokalisasi dalam metodenya masingmasing. Anda tidak dapat mengaksessebuahvariabellokaldariluarmetodeyangmenjadi"rumahnya".Namun Andadapatmemilikilebihdarisatuvariabeldengannamayangsamaasalkanmereka tidakberadadalamsatumetodeyangsama. Adalahsebuahideyangbrillianuntuktetapmenggunakannamanamavariabelyang berbedameskipunvariabelvariabelitutidakberadadalamsatumetodeyangsama.Ini sematamatadilakukanuntukmenghindarikebingungan.Namundalambeberapakasus, terkadangakanlebihbaikjikakitamenggunakannamavariabelyangsama.Sebagai contoh, adalah sebuah tradisi atau keumuman dalam dunia pemrograman untuk menggunakannamanamavariabelsepertii,j,danksebagainamanamavariabeluntuk loop.JikaAndabersikerasuntukmenghindaripenggunaanketigavariabelinidalam sebuahmetodehanyakarenaAndatelahmenggunakannyadimetodelainnya,mungkin Andajustruakanmembuatprogramtersebutsemakinsulituntukdibaca.
6.10 Generalisasi.Sekalilagidengannya....
Sebagaisatucontohgeneralisasilagi,silahkanmembayangkansebuahprogramyang dapatmencetaktabelperkaliandenganukuranberapapun,tidakhanyaberupatabel6x
135
publicstaticvoidprintMultTable(inthigh){ inti=1; while(i<=high){ printMultiples(i); i=i+1; } } Saya mengganti nilai 6 dengan paramater yang saya namai; high . Jika saya memanggilprintMultTable sebagaiberikut: 123456 24681012 369121518 4812162024 51015202530 61218243036 71421283542 Kerenbukan? Kecualibahwamungkinsayamenginginkanhasildiatasagartampak lebih kotak (jumlah baris dan kolom yang sama; 7 x 7 bukan 7 x 6). Untuk mewujudkannya, saya harus menambahkan parameter lain dalam metode printMultiples , untuk menspesifikasikan berapa jumlah kolom yang harus denganargumen7,sayaakanmendapatkanoutput
dimilikiolehtabeltersebut. AgarAndalebihwaspada,sayajugaakanmenamaiparameterinidengannamahigh.
136
Hal ini akan menunjukkan kepada Anda semua bahwa dua atau lebihmetode yang berbedadapatmemilikiparameterparameterdengannamayangsama(persisseperti variabelvariabellokal): public static void printMultiples { inti=1; while(i<=high){ System.out.print(n*i+""); i=i+1; } newLine(); } publicstaticvoidprintMultTable(inthigh){ inti=1; while(i<=high){ printMultiples(i,high); i=i+1; } } Perhatikan bahwa ketika saya menambahkan sebuah parameter baru, saya harus mengubahbarispertamadarimetodetersebut(antarmukaatauprototipenya).Selainitu, saya juga harus mengubah tempat di mana metode itu dipanggil dalam metode printMultTable .Sepertiyangdiharapkan,programinimampumembuatsebuah (int n, int high)
36912151821 481216202428 5101520253035 6121824303642 7142128354249 KetikaAndatelahmenggeneralisasisebuahmetodedengantepat,terkadangAndaakan menjumpaiprogramyangAndahasilkanternyatamemilikikapabilitasataukemampuan yang tidak persis seperti Anda harapkan. Sebagai contoh, Anda mungkin memperhatikan bahwa tabel perkalian yang kita buat sebelumnya memiliki sifat simetris.Haliniterjadikarenasifatkomutatifdalamperkalianyakniab = ba .Jadi, semuaentriyangberadadalamtabelakandicetak2kali.Andadapatmenghemattinta dengan cara mencetak tabel tersebut setengah dari ukuran normalnya. Untuk melakukannya, Anda cukup mengganti sebuah baris dalam metode printMultTable .Ubahlahperintah:
138
Saya akan tinggalkan bagian ini khusus untuk Anda agar Anda dapat menemukan bagaimanaprogramtersebutdapatmenghasilkanoutputyangsedemikianrupa.
6.11 DaftarKataKata
Istilah Loop Infiniteloop Body Iterasi Enkapsulasi Arti Sebuahpernyataanyangdieksekusiberulangulangselamaatau sampaibeberapasyarat/keadaan(condition)dipenuhi. Sebuahloopyangsyarat/kondisinyaselalubernilaibenar. Pernyataanyangberadadalamloop. Prosessatukalieksekusiyangterjadidalambadan(body)loop, termasukdidalamnyaadalahpengecekannilaisyarat/kondisi. Membagisebuahprogramyangbesardankomplekskedalam komponenkomponenkecil(sepertimetode)untukkemudian mengisolasinyadarikomponenkomponenlainnya(contoh, dengancaramenggunakanvariabellokal). Variabellokal variabelyangdideklarasikandidalamsebuahmetodedaneksis hanyadidalammetodetersebut.Variabellokaltidakdapat diaksesdariluarmetodeyangmenjadi"rumah"mereka. Variabelinijugatidakakanberinterferensi(bertabrakan) denganmetodemetodelainnya. Generalisasi Menggantisesuatuyangspesifik tapitidakpenting(misalnya nilai konstan) dengan sesuatu yang lebih cocok/tepat secara umum(sepertivariabelatauparameter).Generalisasimembuat kodelebihfleksibel,memungkinkanuntukdigunakankembali, danterkadanglebihmudahdannyamanuntukdibaca. Developmentplan Suatuprosesuntukmengembangkansebuahprogram.Dalam
139
Istilah
6.12 Latihan
Latihan6.1
public static void main (String[] args) { loop (10); } public static void loop (int n){ int i= n; while (i >0) { System.out.pr i =i/2; }else { i =i+1; } } } intln (i); if(i%2 == 0){
satubarisuntuksetiapiterasi. b) Apaoutputdariprogramini?
141
Sebagaicontoh,jikakitahendakmenemukanakardari9.Kitabisamemulaitebakan kitadenganxo=6,kemudianx1=(6+9/6)/2=15/4=3.75.Lihat,mulaimendekati bukan? Kitadapatmengulangiprosedurini,denganmenggunakanx1untukmenghitungnilaix2, x2untukx3,laluseterusnya.Dalamcontohyangkitagunakan,berartix2=3.075danx3 =3.00091.Begituseterusnya,sampaimendekatinilaipendekatanyangkitatetapkan. BuatlahsebuahmetodedengannamasquareRootyangmenggunakansebuahvariabel bertipe double sebagai parameter dan mengembalikan sebuah nilai pendekatan dari parameter tersebut, dengan menggunakan algoritma di atas tentunya. Anda dilarang menggunakanmetodeMath.sqrtyangmerupakanmetodebawaan(builtin)Java. Gunakan a/2 sebagai nilai awal tebakan Anda. Metode Anda harus melakukan perulangan (iterasi) sampai metode ini menghasilkan dua nilai pendekatan yang berurutan dan juga memiliki selisih kurang dari 0.0001. Anda dapat menggunakan metodeMath.absuntukmenghitungnilaimutlak.
Latihan6.4 Dalam latihan 5.9 kita telah menulis sebuah versi rekursif untuk mencari bilangan pangkat(power)yangmenggunakanvariabel x bertipe double dan n bertipe integer
142
serta mengembalikan nilai xn. Sekarang, tulislah sebuah metode iteratif untuk melakukanhalyangsama.
Jikavariabelloopkitanamaidengani,makaurutantermyangkeiakansamadengan xi/i!. a) Buatlahsebuahmetodedengannama myexp yangmampumenjumlahkan n term pertamadaribentukdiatas.Andadapatmenggunakanmetodefactorialdaribagian 5.10atauversiiteratifnya.Terserah! b) AndadapatmembuatmetodeinilebihefisienjikasajaAndasadarbahwadalam setiap iterasi, nilai numerator dari term sama dengan nilai predecessornya (sebelumnya)dikalidenganx,sementaradenominatornyaadalahsamadengannilai predecessornya dikali dengan i. Gunakan hasil analisa ini untuk meniadakan penggunaanMath.powdanfactorial,laluperiksalahkembalidengancermatbahwa Andamasihtetapakanmendapatkanhasilyangsama. c) Buatlahsebuahmetodedengannamacheck,yangmenggunakansebuahparameter, yakni x.MetodeAndainiakanmemilikikemampuanuntukmencetaknilaidari x, Math.exp(x) dan myexp(x) untuk berbagai variasi nilai dari x. Hasil yang akan 143
ditampilkanharustampaksepertiberikut: 1.02.7083333333333332.718281828459045 Petunjuk:AndadapatmenggunakanString"\t"untukmencetaksebuahkaraktertab diantarakolomkolomdalamtabeltersebut. d) Ubahubahlah (variasikan) nilainilai term (argumen kedua yang dikirimkan oleh metodecheckkepadamyexp),lalulihatlahpengaruhnyaterhadapakurasidarihasil tersebut.Cocokkannilaiinihingganilaiyangdiperkirakan(estimasi)sesuaidengan jawabanketikaxsamadengan1. e) Tulislahsebuahloopdalammainyangmemanggilmetodecheckdengannilai0.1, 1.0,10.0,dan100.0.Lihatbagaimanaakurasi(ketepatan)darihasilyangditampilkan ketikanilai x jugabervariasi.Bandingkanjumlahdigitdari agreement ketimbang membandingkanperbedaanantaranilaiaktualdannilaiperkiraan. f) Tambahkan sebuah loop dalam main yang berfungsi untuk memeriksa myexp dengannilai 0.1,1,0,10.0, dan 100.0.Berilahtanggapanuntukketepatanyang dihasilkan. Latihan6.7 Salahsatucarayangdigunakanuntukmengevaluasibentuk e^(x^2) adalahdengan menggunakanbentukekspansitakhinggaberikut: e^(x^2) = 12 x + 3x 2/ 2! 4x 3 /3! + 5x 4 /4! ...... (6.4) Dengankatalain,kitaperlumenambahkanbeberapatermdimanatermyangkeiakan sama dengan (1)i (i+1) xi / i!. Buatlah sebuah metode dengan nama Gauss yang menggunakan x dan n sebagai argumen. Metode ini akan mengembalikan nilai penjumlahan dari nterm pertama. Anda tidak diperkenankan untuk menggunakan metodefactorialataupow. 144
Dalam Java dan bahasa pemrograman berorientasi objek lainnya, objek merupakan koleksi dari data dan sekumpulan metode yang saling berkaitan. Metodemetode digunakan untuk melakukan operasioperasi tertentu dalam objek, mengerjakan perhitungandanterkadangmemodifikasidatamilikobjekitusendiri. Diantarasemuatipedatayangtelahkitabahassampaisaatini,hanyaStringyangdapat dikategorikansebagaisuatuobjek.Berdasarkanpengertianobjekyangtelahkitaungkap diatas,mungkindiantaraAndaakanadayangbertanya,dataapayangdimilikioleh suatuStringyangjugaberstatusobjek?danmetodemetodeapasajayangdapatkita panggiluntukmemfungsikanobjekobjekyagberupaString? DatayangterkandungdalamobjekStringadalahhurufhurufdaristringitusendiri. Sebenarnyaadacukupbanyakmetodeyangdapat digunakan untukmengoperasikan atau beroperasi dalam objekobjek String, tapi di buku ini Saya hanya akan menggunakanbeberapadiantaranyasaja.SisanyadapatAndasimak dalamhalaman berikut: http://java.sun.com/javase/6/ docs/api/java/lang/String.html MetodepertamayangakankitabahasadalahcharAt.MetodeinidapatAndagunakan untuk mengambil/mengekstrak hurufhuruf yag berada dalam sebuah String. Untuk menyimpanhasilpengambilantersebut,kitamembutuhkansebuahvariabelyangdapat menyimpanhurufhuruftersebutsebagaisebuahsatuantersendiri(kebalikandariString itusendiriyangmerupakansekumpulanitemitemyangberurutan).Satusatuanhuruf
145
itu disebut sebagai karakter (character), dan tipe data yang digunakan untuk menyimpannyadisebutdenganchar. char bekerjadengancarayangsamasepertitipedatatipedatayangsudahkitalihat sebelumnya: charfred='c'; if(fred=='c'){ System.out.println(fred); }
Nilai karaktertampildalamkurungantandapetiksatu 'c'.Iniberbedadengannilai variabelbertipedataStringyangdiapitdengantandapetikganda().Nilaivariabel bertipedatacharhanyabolehmengandungsatuhurufatausatusimbolsaja.Berikutini adalahcaramenggunakanmetodecharAt: Stringfruit="banana"; charletter=fruit.charAt(1); System.out.println(letter); Sintaksfruit.charAtmengindikasikanbahwaSayasedangmemanggilmetodecharAt dalamsebuahobjekyangbernamafruit.ArgumenyangSayalewatkan(pass)untuk metode ini adalah1.Halini mengindikasikan kepadaAnda bahwasaya tampaknya inginmengetahuihurufpertamadaristringtersebut.Hasilnyaadalahsebuahkarakter yangsayasimpandalamsebuahvariabelbertipedatachar,yakniletter.Ketikasaya mencetaknilaivariabelletteritu,sayapunterkejut: a Hei....bukankahaituhurufkedua?Andajugamungkinakanterkejut,kecualikalau AndaadalahseorangComputerScientist.Untukbeberapaalasantertentu,parailmuwan 146
komputercenderunguntukmemulaiperhitungandari0.hurufyangberadapadaurutan ke0dalamstringbananaadalahb.sedangkanurutanyangke1adalaha,urutanke2 adalahn,dst.Jadi,jikaAndamenginginkanhurufyangberadapadaurutanke0dari sebuah string, Anda harus menggunakan 0 sebagai argumen yang Anda lewatkan. Simaklahkodeberikutini: charletter=fruit.charAt(0);
7.2
Length
MetodekeduauntukStringyangakankitabahasadalahlength.Metodeiniberfungsi untukmengembalikanjumlahkarakteryangmenyusunsuatustring.sebagaicontoh: intlength=fruit.length(); lengthtidakmembutuhkanargumenapapun.Halinidapatdilihatdaritanda()yang memangtidakterisidenganapapun.Metodeiniakanmengembalikannilaiyangbertipe integer, dalam kasus di atas, nilai yang dikembalikan adalah 6. Perhatian! Adalah sesuatuyanglegaldalamJavauntukmenamaisebuahvariabeldengannamayangsama seperti nama metode. Namun Anda harus tetap hatihati karena hal ini dapat menimbulkankebingunganuntukpenggunayangsedangmembacakodetersebut. Untukmencarinilaiakhirdarisebuahstring,terkadangAndamungkinakantergoda untukmelakukansesuatusepertiyangtampakdalamduabarisberikut: intlength=fruit.length(); charlast=fruit.charAt(length); //wrong!! Itutidakakanberhasil.Mengapa?Karenamemangtidakadahurufke6dalamstring banana.Ingat!Kitamelakukanperhitungandariangka0.Jadi,stringyangmemiliki6 hurufakandiurutmenggunakannomorurutan0hingga5,bukan1hingga6.Untuk mendapatkan karakter terakhir, Anda harus mengurangkan length dengan angka 1. Perhatikankodeberikut: 147
intlength=fruit.length(); charlast=fruit.charAt(length1);
7.3
Traversal
Pola/hal umum yang sering dijumpai dalam bentukbentuk string adalah kegiatan berikut;mulailahdariawal,pilihlahsetiapkaraktersecarabergantian,lakukansesuatu terhadap karakter itu, lalu lanjutkan hingga karakter terakhir. Pola pemrosesan ini dikenal dengan sebutan traversal. Cara alami untuk mengenkode sebuah traversal adalahdenganmenggunakanpernyataanwhile: intindex=0; while(index<fruit.length()){ charletter=fruit.charAt(index); System.out.println(letter); index=index+1; } Loop di atas akan mentraverse string dan mencetak setiap huruf dalam satu baris. Perhatikan bahwa syarat yang digunakan dalam kode di atas adalah index < fruit.length().Artinya,ketikaindexsamadenganpanjangdaristring,syarattersebut akan bernilai false. Akibatnya, badan dari loop itu tidak akan dieksekusi. Karakter terakhiryangkitaaksesadalahkarakterdenganurutanfruit.length()1. Namadarivariabelloopadalahindex.Satuindexmerupakansuatuvariabelataunilai yangdigunakanuntukmenentukansatuanggotadarisebuahhimpunanberurutan(baca: himpunan karakter yang berada dalam string). Index ini akan menentukan karakter mana (baca: nama karakter tersebut) yang Anda inginkan. Himpunan ini haruslah merupakansuatuhimpunanberurutanagarsetiaphurufdapatmemilkiindexdansetiap indexdapatmengacukepadasatukaraktersaja. 148
Sebagai latihan, tulislah sebuah metode yang menggunakan String sebagai sebuah argumen dan yang mampu mencetak semua huruf dalam posisi yang berkebalikan (backwards).Cetaksemuahuruftersebutdalamsatubaristampilansaja.
7.4
RunTimeerrors
Kembalilagikebagian1.3.2,disanasayatelahmenyinggungsedikitmengenairun timeerrors.Istilahinidigunakanuntukmenunjukkansuatuerrordalamprogramyang tidakakanditampilkankecualikalauprogramitutelahdijalankan(running).Dalam Java,runtimeerrordisebutjugadenganexceptions. Sejauhini,Andamungkinbelumterlaluseringmelihatruntimeerrors.Maklumsaja, inikarenakitamemangbelumbanyakmengerjakansesuatuyangdapatmenyebabkan terjadinyaruntimeerrorsitusendiri.Nah,sekaranglahsaatnya.JikaAndamenggunakan perintahcharAtlalupadasaatyangbersamaanAndajugamenggunakansebuahindex yangbernilainegatifataulebihbesardarilength1,makaAndaakanmenjumpaisebuah exceptions.Dalamkasusini;StringIndexOutOfBoundsException.Cobalahdanlihat bagaimanaexceptionsinibekerja. JikaprogramAndamenyebabkanterjadinyasuatuexceptions,makaprogramtersebut akan mencetak sebuah pesan error yang mengindikasikan tipe exceptions sekaligus lokasiterjadinyaerrortersebutdalamprogramAnda.
7.5
Jika
MembacaDokumentasi
Anda mengunjungi situs
149
Returns the character at the specified index. Anindex ranges from 0 tolength() 1. Parameters: index the index ofthe character. Returns: the character atthe specified index of this string. The first character is atindex 0. Throws: StringIndexOut outof range. OfBoun dsExce ption if the index is
BarispertamaadalahprototipemilikmetodecharAtyangberisinamadarimetodeini, tipedatadariparameterdannilaipengembalianyangdigunakan. Baris berikutnya menginformasikan manfaat/fungsi dari metode. Berikutnya, merupakaninformasimengenaiparameterparameter dannilaipengembalian.Dalam kasus ini, penjelasan yang diberikan mungkin terkesan berulangulang, tapi dokumentasisepertiinilahyangmerupakanbentukstandardokumentasidalamJava. Baris terakhir akan menjelaskan kepada kita mengenai exceptions, kalau memang benarbenarada,yangdapatdisebabkankarenapenggunaanmetodeini.
7.6
MetodeindexOf
Dalambeberapahal,indexOfdapatdisebutsebagailawan(anti)darimetodecharAt. Alasannya?InikarenacharAtbekerjadengancaramengambilnilaisebuahindexlalu mengembalikan karakter yang diacu (diindeks) pada indeks tersebut. Sementara indexOf bekerja dengan cara mengambil sebuah karakter lalu mengembalikan nilai indekstempatdimanakaraktertersebutberada. charAtakangagalmanakalaindeksyangdimintanyaberadadiluarjangkauan.Halini akanmenyebabkanterjadinyaexceptionspadaprogram.LaindenganmetodeindexOf yangakanmengalamikegagalanjikakarakteryangdimintatidakberadadalamstring yangdimaksud.Padasaatkasussepertiiniterjadi,metodeiniakanmengembalikannilai 150
1. Stringfruit="banana"; intindex=fruit.indexOf('a'); Kode di atas digunakan untuk menemukan indeks (lokasi) huruf ' a ' dalam string banana.Menariknya,hurufyangkitainginkanternyatamunculsebanyak3kali.Jadi, metodeini(seharusnyaAndajuga)mungkinakanmengalamikebingungankarena tidaktahuharusmengembalikannilaiindeksyangmanauntukhuruf'a'.Dalamkasus kasussepertiinilahterkadangsebuahdokumentasimenjadisangatbermanfaat.Bilakita mengacupadainformasidalamdokumentasi,kitaakantahubahwametodeindexOf akanmengembalikannilaiindeksdarikemunculankarakter'a'yangpertamakali(a diindekspadaurutanyangpertama.Ingat,Javamemulaiindeksdariurutan0bukan1). Untukmenemukanindeksdarikemunculanberikutnya,adaversialternatifdarimetode indexOf (penjelasanlebihlanjut mengenaikasus overloadingsemacamini, silahkan membukakembalibagian5.4).Kitamembutuhkanargumenkeduayangakanberfungsi untukmenginformasikanlokasipadastringdimanakitaakanmemulaipencarian.Jika kitamemanggil intindex=fruit.indexOf('a',2); kode ini akan mulai melakukan pencarian pada huruf yang berada di urutan kedua (sekalilagiingat,dalamJavainiberartihuruf'n'bukan'a'),danakanlangsung menemukankarakterayangkeduapadaindeksketiga.Jikahurufyangdicaritepat beradapadaindeksdimanakitamemulaipencarian,makaindeksinisendirilahyang menjadijawaban(nilaiyangdikembalikanolehindexOf).Dus, intindex=fruit.indexOf('a',5); akan mengembalikan nilai 5. Kalau kita membaca kembali dokumentasi resmi mengenai metode ini, mungkin tidak ada salahnya jika kita sedikit bereksperimen dengan cara memberikan nilai indeksmulai pencarian yang lebih besar ketimbang 151
jangkauanstringyangkitamaksudkan: Metode indexOf mengembalikan nilai indeks dari karakter pertama yang berada dalam string yang direpresentasikan melalui objek yang lebih besar atau sama dengan indeksmulai, atau 1 jika karakter yang dimaksud tidak berada dalam string tersebut. indexOfreturnstheindexoftherstoccurrenceof thecharacterinthecharactersequencerepresented by this object that is greater than or equal to fromIndex,or1ifthecharacterdoesnotoccur.
Salahsatucarauntukmengetahuimaksud'aneh'dokumentasidiatasadalahdengan mengujicobanya.Berikuthasilujicobasaya:
Jika indeksmulai lebih besar atau sama dengan length(), hasil yang akan dikembalikan adalah 1. Hasil ini mengindikasikan bahwa huruf yang dicari/diinginkantidakberadadalamindeksyanglebihbesardaripadaindeks mulai.
Jika Anda membaca ulangdokumentasitersebut,Anda akan memahamibahwadua keadaandiatasmemangsesuaidengandefinisiyangadadalamdokumentasi.Meskipun mungkindefinisitersebutawalnyatidaklahterlalujelas.Nah,karenakitasemuasudah mengetahui cara kerja indexOf dengan benar, sekarang barulah kita bisa 152
menggunakannyadalamprogramprogramyangakankitabuat.
7.7
LoopingdanCounting
Programberikutiniakanmenghitungfrekwensikemunculanhuruf'a'dalamstring:
Stringfruit="banana"; intlength=fruit.length(); intcount=0; intindex=0; while(index<length){ if(fruit.charAt(index)=='a'){ count=count+1; } index=index+1; } System.out.println(count); Program ini menunjukkan sebuah istilah populer dalam dunia pemrograman, yakni counter. Variabel count awalnya diinisialisasi dengan nilai 0 lalu kemudian secara bertahapakandinaikkannilainyatiapkaliprogrammenemukan'a'.Ketikakitakeluar dariloop,countakanberisinilaiyangberupajumlahtotal'a'yangditemukandalam string. Sebagailatihanawal,enkapsulasilahkodeinikedalamsebuahmetodedengannama countLetters.Lalugeneralisasilahkodeitusehinggadapatmenerimastringdanhuruf sebagaiargumenargumen. Untuk latihan yang kedua, tulisulanglah metode itu dengan memasukkan indexOf
153
untuk mencari letak huruf yang diinginkan ketimbang melakukan pemeriksaaan karakterkaraktertersebutsatupersatu.
7.8
OperatorIncrementdanDecrement
Sebelumkitapergilebihjauh,adabaiknyajikakitapahamiterlebihdahuluapayang dimaksuddenganincrementdandecrement.
Baikincrementmaupundecrementsebenarnyahanyaoperatorbiasa.Namun,dalam Java,keduanyamemangmendapatkanoperatorkhusus,yakni'++'untukincrement dan''untukdecrement.Operator++akanmenambahkansatu(1)untuknilaiyang sedangdisimpanolehsuatuvariabelyangbertipeintatauchar.Sementaraoperator'' akanmengurangisatu.Keduanyatidakdapatdigunakanuntukvariabelbertipedouble, boolean,atauString. Secara teknis, adalah legal dalam Java untuk mengincrement suatu variabel, untuk kemudianlangsungmenggunakannyadalamsebuahekspresi.Sebagai contoh,Anda bolehmembuatekspresisepertiberikut: System.out.println(i++); Melihatekspresisepertiini,hasilyangakanditampilkantentunyabelumjelas,apakah increment yang kita lakukan akan bekerja sebelum nilai tersebut dicetak ataukah sesudahnya.Mengingatekspresiekspresisepertiinidapatmenimbulkankebingungan, sayatidakmenganjurkankepadaAndauntukmemakainya.DanuntukmembuatAnda lebihtidakinginmemakainya,sayatidakakanmemberitahuAndahasilekspresidi atas.NamunjikaAndasungguhsungguhhendakmengetahuinya,cobasajasendiri! 154
Menggunakanoperatorincrement,kitadapatmenulisulanglettercounter: intindex=0; while(index<length){ if(fruit.charAt(index)=='a'){ count++; } index++; } Andaakanmenjumpaipesanerrorjikamenulisekspresisepertidibawahini: index=index++;//WRONG!! Sayangnya, ekspresi tersebut dianggap legal secara sintaks. Jadi, kompiler Java mungkintidakakanmemberikanperingatanuntukAndasebelumnya.Dampakyang timbuldaripernyataaniniadalahtidakberubahnyanilaivariabelindexyangseharusnya hendakkitaubah.Kesalahansepertiiniterkadangmenjadibugyangsulituntukdilacak keberadaannya. Ingatlah,Andadapatmenulisekspresi index=index+1; atau index++; tapisebaiknyajangansampaimencampur/menggabungnya.
7.9
StringsareImmutable
diubahubah. Simakyangberikutini!KetikaAndamemanggiltoUpperCasedalamsebuahString, AndaakanmendapatkansebuahString baru (untuksementaraanggapsajademikian) sebagaihasildarinilaiyangdikembalikanolehmetode.Sebagaicontoh: Stringname="AlanTuring"; StringupperName=name.toUpperCase(); Setelahbariskeduadieksekusi,upperNameakanberisinilaiALANTURING,tapi tidakjuga,karenasebenarnyavariabelnamemasihberisiAlanTuring.
7.10 StringsareIncomparable
Terkadang ada saatsaat dimana membandingkan dua string merupakan hal yang penting.Perbandinganinidigunakanmisalnya;untukmelihatapakahduastringyang dibandingkan tersebut sama ataukah tidak, atau untuk melihat string manakah yang berada di depan string lainnya bila dilihat secara alfabetis (in alphabetical order). Senang rasanya jika kita dapat menggunakan operatoroperator perbandingan yang sudahada,seperti==dan>,tapisayang,Javatidakmengizinkannya. UntukmembandingkanString,kitaharusmenggunakanmetodeequalsdancompareTo. Contoh: Stringname1="AlanTuring"; Stringname2="AdaLovelace"; if(name1.equals(name2)){ System.out.println("Thenamesarethesame."); } intflag=name1.compareTo(name2); if(flag==0){ 156
System.out.println("Thenamesarethesame."); }elseif(flag<0){ System.out.println("name1comesbefore name2."); }elseif(flag>0){ System.out.println("name2comesbefore name1."); } Sintaks yang Anda lihat di atas mungkin kelihatan aneh (yaa, gitu deh). Untuk membandingkanduastring,Andaharusmemanggilsebuahmetodemelaluisalahsatu stringitulalumelewatkanyanglainnyasebagaiargumennya. Nilai kembalian dari metodeequals terkesan lugas danjelas; true jika kedua string berisikarakterkarakteryangsama,danfalsejikatidak. Namun nilai yang dikembalikan oleh compareTo terkesan agak ganjil alias aneh. Parameteryangdibandingkanadalahkarakterpertamadalamstringsaja.Jikakedua string itu sama, maka nilai kembalian adalah 0. Jika string pertama (string tempat metode compareTodipanggil)mendahuluistringkeduadalamurutanalfabetis,nilai kembalian akan negatif. Jika tidak, maka nilainya positif. Dalam contoh ini, nilai pengembaliannya adalah 8. Ini disebabkan karena huruf kedua dalam string Ada LovelacemendahuluihurufkeduastringAlanTuringsebanyak8huruf(hurufDdan Lterpisahsebanyak8hurufdalamalfabet;caramenghitung;EFGHIJKL). MenggunakanmetodecompareToterkadangmalahmerepotkan.Meskipunbegitu,sisi positifdarimetodeiniadalahbahwainterfaceyangdigunakannyabisadibilangcukup lumayansebagaistandaruntukmembandingkanberbagaitipeobjek.Jadi,ketikaAnda sudahmemahamicaramenggunakannya,Andaakanlebihsiapuntukyanglainnya.
157
7.11 DaftarKataKata
Istilah Object Arti Sebuahkoleksiyangmengandungdatayangsalingberkaitan dansekumpulanmetodeyangdapatberoperasididalamnya. Objek yang telah kita gunakan sejauh ini adalah objek GraphicyangdisediakanolehsystemdanString. Index Sebuahvariabelataunilaiyangdigunakanuntukmemilihsatu anggotadarisuatuhimpunanterurut.Misalnya,satukarakter dalamstring. Traverse Counter Melakukan suatu operasi yang sama secara berulangulang untukseluruhelemenyangberadadalamsebuahhimpunan. Sebuahvariabelyangdigunakanuntukmenghitungsesuatu. Variabel ini biasanya diinisialisasi dengan nilai 0 lalu dinaikkansatusatusecarabertahap(increment). Increment menaikkan/menambahkan nilaisuatuvariabeldengannilai satu(1)secaraberulangulangsampaisyaratyangditetapkan bernilaifalse.Operatornyaadalah++ Decrement menurunkan/mengurangi nilaisuatuvariabeldengannilai satu(1)secaraberulangulangsampaisyaratyangditetapkan bernilaifalse.Operatornyaadalah Exceptions Sebuahruntimeerror.Exceptionsmenyebabkanterhentinya 158
proseseksekusisebuahprogram.
159
e) Ujilah!Lalulihatlahpesanerroryangkeluar.Janganlupa,berusahalahjugauntuk memahamiapayangsebenarnyaterjadidenganerroritu.
Latihan7.2
Apakahoutputyangakandihasilkanprogramini?Ungkapkanlahdalamsebuahkalimat, secaraabstrak,sebenarnyaapasihbingitu(tapibukanbagaimanacaraiabekerja)? publicclassMystery{ publicstaticStringbing(Strings){ inti=s.length()1; Stringtotal=""; while(i>=0){ charch=s.charAt(i); System.out.println(i+""+ch); total=total+ch; i; } returntotal; } publicstaticvoidmain(String[]args){ System.out.println(bing("Allen")); } }
Latihan7.3
160
Salah seorang temanmu menunjukkan metode berikut ini kepadamu. Ia juga menjelaskanbahwajikavariabelnumberadalahsemuabilanganyangterdiridaridua digit,makaprogramakanmengeluarkanbilangantersebutsecaraterbalik(backward). Diamengklaimbahwakalaunumbersamadengan17,outputakansamadengan71. Benarkahitu?Jikatidak,jelaskanapayangsebenarnyadikerjakanolehprogram.Lalu modifikasilahprograminisehinggabisaberfungsidenganbaikdantepat. intnumber=17; intlastDigit=number%10; intfirstDigit=number/10; System.out.println(lastDigit+firstDigit);
Latihan7.3
Apakahoutputdariprogramini? publicclassRarefy{ publicstaticvoidrarefy(intx){ if(x==0){ return; }else{ rarefy(x/2); } System.out.print(x%2); } publicstaticvoidmain(String[]args){ rarefy(5);
161
System.out.println(""); } } Jelaskandalam4s.d.5katatentangapayangsebenarnyadikerjakanolehmetodeini.
Latihan7.5
a) BuatlahsebuahprogramdengannamaPalindrome.java. b) BuatlahsebuahmetodedengannamafirstdanlastyangmenggunakansebuahString sebagai parameter. Metode first hanya akan mengembalikan karakter awal dari stringsementaralasthanyaakanmengembalikankarakterterakhirdaristringitu. c) Buatlah sebuah metode dengan nama middle yang menggunakan String sebagai parameter. Metode ini akan mengembalikan sebuah substring yang mengandung semuaanggotastringtersebutkecualikarakterawaldanakhirnya. Petunjuk: bacalah dokumentasi mengenai metode substring dalam kelas String. EksekusilahbeberapaujicobayangdapatmembuatAndamengertibagaimanacara substringbekerjasebelumAndamenulismiddle. ApayangakanterjadijikaAndamemanggilmiddledalamsebuahstringyanghanya berisiduahurufataukarakter?Satukarakter?Tanpakarakter?Hmmm... d) Pengertianumumuntukpalindromeadalahsebuahkatayangapabiladibacabaikdari depanmaupundaribelakangakanmenghasilkanejaanbacayangsama.Contohnya; otto,palindromeemordnilap.Caraalternatifuntukmendefinisikankasuskasus sepertiiniadalahdenganmenentukansebuahmetodekhususdanspesifikyangdapat digunakanuntukmengujikasusitusendiri.Misalnya,mungkinkitasemuasepakat berkata,satuhurufyangtunggaltermasukpalindrome,dansebuahkatayangterdiri dariduahuruftermasukpalindromejikakeduahurufadalahsama,dansemuakata yanglainadalahpalindromejikahurufpertamadanterakhiradalahsamasementara
162
katayangberadadiantaranyatermasukpalindrome. Buatlahsebuahmetodedenganteknikrekursif,isPalindrome, yangmenggunakan sebuahStringsebagaiparameterdanmampumengembalikansebuahnilaiboolean yang dapat dijadikan penanda apakah kata yang Anda masukkan termasuk palindromeataukahbukan. e) JikaAndasudahmempunyaimetodepemeriksapalindromeyangdapatberfungsi dengan baik, carilah cara untuk menyederhanakannya dengan cara mengurangi jumlahpersyaratan(conditions)yangharusdiperiksa. Petunjuk:mungkinakanbergunabagiAndauntukmenetapkanstringkosongsebagai palindrome. f) Diatasselembarkertas,rancanglahsebuahstrategiiteratifuntukmemeriksabentuk palindrome. Ada beberapa pendekatan yang mungkin bisa dipakai untuk menyelesaikan ini, jadi buatlah rencana yang matang terlebih dahulu sebelum menuliskodenya. g) Implementasikan strategi yang sudah Anda putuskan ke dalam sebuah metode dengannamaisPalindromeIter.
Latihan7.6
Sebuah kata dapat dikategorikan sebagai abecedarian jika hurufhuruf dalam kata tersebutmunculdalamurutanyangalfabetis(dariAkeZ).Sebagaicontoh,19katadari bahasainggrisberikutinimerupakanabecedarianyangsemuanyaterdiridari6huruf. abdest, acknow, acorsy, adempt, adipsy, agnosy, best, behint, beknow, bijoux,biopsy,cestuy,chintz,deux,dehors,dehort,deinos,diluvy,dimpsy a) Deskripsikansebuahalgoritmauntukmemeriksaapakahkata(String)yangdijadikan argumendapatdigolongkansebagaiabecedarian.Asumsikanbahwasemuakata hanyabolehberisihurufkecil(lowercase).AlgoritmaAndabisabersifatrekursif
163
ataupuniteratif. b) ImplementasikanalgoritmaAndadalammetodeyangdisebutdenganisAbecedarian.
Latihan7.7
dupledromeadalahsebuahkata yanghanyabolehmengandunghurufganda,seperti llaammaaataussaabb.Sayamendugabahwatidakadasatupundupledromedalam katakata bahasa inggris yang sering digunakan. Untuk menguji dugaan itu, saya menginginkansebuahprogramyangdapatmembacasetiapsatukatadalamkamuslalu memeriksanya,kemudianmemberitahuapakahkataitutermasukdalamdupledromity juga. Tulislah sebuah metode isDupledrome yang mengambil sebuah String sebagai parameter. Metode ini akan mengembalikan sebuah nilai bertipe boolean yang mengindikasikanapakahsuatukatamemilikisifatdupledromitas.
Latihan7.8
Ketikanamanamatelahdisimpandalamkomputer,terkadangnamanamaituditulis secara langsung, yakni dengan menempatkan nama depan di depan nama belakang, sepertiAllenDowney,atausebaliknya,dengancaramenempatkannamabelakangdi depan nama depan namun di antara keduanya diberi tanda koma, seperti Downey, Allen.Keadaaninidapatmenyulitkankitauntukmembandingkannamanamatersebut danmenempatkannyadalamurutanyangalfabetis. Masalahyangmasihadakaitannyadenganhalsemacaminiadalahbahwabeberapa individu memiliki nama dengan penempatan huruf kapital yang lucu, seperti teman saya, BethDeSombre,ataubahkantanpasatuhurufkapitalpun, seperti poete.e. cummings. Ketika komputerkomputer digunakan untuk membandingkan karakter karakter, mereka cenderung menempatkan semua huruf kapital dalam susunan yang salah. 164
Jika Anda mau, lihatlah buku telepon umum, seperti buku direktori kampus, lalu cobalahpahamibagaimanateknikyangdipakaiolehbukuituuntukmenuliskannama namayangadadidalamnya.Perhatikannamanamayangmengandungbeberapakata sekaligussepertiVanHouten juga namanama dengan huruf kapital yang non
standar, seperti desJardins. Coba lihat, apakah Anda sanggup untuk merancang aturan/ramburambupengurutannya.JikaAndamemilikiakseskebukuteleponnegara negaradieropa,cobajugaitu,dantelitilahkalaukalauaturanyangdigunakanjuga berbedadenganstandarAmerika. Hasildarisemuabentuknonstandariniadalahbahwaterkadangtidaklahtepatuntuk mengurutkannamanamatersebutmenggunakanaturanStringyangbiasa.Satusolusi yangumumadalahdengancaramenyimpanduaversisekaligusuntuktiaptiapnama: pertama, untuk dicetak; kedua, format internal yang digunakan untuk melakukan pengurutan. Dalam latihan kali ini, Anda diminta menulis sebuah metode yang akan membandingkanduanamadengancaramengkonversikankeduanyakedalamformat standar.Kitaakanbekerjadaribawahkeatas(bottomup),menulisbeberapametode penolonguntukkemudianbarumenulismetodecompareName. a) BuatlahsebuahprogramdengannamaName.java.DalamdokumentasiuntukString, bacalah tentang metode find, toLower, dan compareTo. Buatlah beberapa kode sederhanauntukmengujimasingmasingmetode.PastikanAndadapatmemahami bagaimanacarakerjaketiganya. b) BuatlahmetodehasComayangmenggunakansebuahnamasebagaiargumenserta mampu mengembalikan nilai boolean yang mengindikasikan apakah nama itu mengandungkomaataukahtidak.Jikaya,makaAndasudahdapatmenganggapnya sebagaiformatnamadengannamabelakangmendahuluinamadepan. c) Buatlah metodeconvertName yangmenggunakansebuahnama sebagai argumen. 165
Metode ini harusmemeriksa apakahnama itu mengandung koma.Jika ya,maka metode ini hanya perlu mengembalikan string nama itu saja. Jika tidak, maka anggaplah nama tersebut termasuk dalam format namadepan duluan. Selain itu, metodeini jugaharusmengembalikan sebuahstringbaruyangberisinamayang telahdikonversikankeformatnamabelakangduluan. d) TulislahsebuahmetodedengannamacompareNameyangmenggunakanduabuah nama sebagai argumen dan yang mengembalikan nilai 1 jika nama pertama mendahului nama kedua, dalamurutan abjad alfabet, 0jika kedua nama bernilai samasecaraalfabetis,dan1untukkeadaanlainnya.MetodeyangAndabuatharuslah bersifatcaseinsensitive.Artinya,metodeinitidakakanmemedulikanapakahhuruf hurufpenyusunnamanamayangAndaberikannantinyamerupakanhurufkapital (uppercase)atauhurufnonkapital(lowercase).
Latihan7.9
a) CincinDecoderKaptenCrunchbekerjadengancaramengambilsetiaphurufdalam sebuahstring,lalumenambahkankemasingmasinghuruftersebutnilai13.Sebagai contoh,'a'menjadi'n'dan'b'menjadi'o'.Hurufhuruftersebutkemudianakan berputar(wraparound)dibagianakhir,sehingga'z'akanmenjadi'm'(z+13= m). BuatlahsebuahmetodeyangmengambilsebuahStringsebagaiparameterdanyang mengembalikan sebuah String baru yang mengandung versi enkode dari String tersebut.AndaharusmengasumsikanbahwaStringyangakandilewatkansebagai parameterdapatberisihurufkecil,hurufkapital,danspasi.Tetapitidakuntuktanda baca yang lain. Huruf kecil harus diubah ke dalam huruf kecil lagi, begitu pula denganhurufkapital.Bagaimanadenganspasi?Andatidakperlumengenkodenya. b) GeneralisasilahmetodeinisehinggadapatmenambahkannilaiberapapunyangAnda
166
kehendaki ketimbang hanya mampu menambahkan 13 ke dalam setiap huruf. Sekarang Anda pastinya bisa mengenkode sesuatu dengan menjumlahkan 13lalu mendekodenyadenganmenambahkan13.Ayocoba!
167
MeskipunStringadalahobjek,tapimerekabukanlahobjekyangbenarbenarmenarik. Maklum,Stringitu:
Dalambagianini,kitaakanmenggunakanduatipeobjekbaruyangmerupakanbagian dariJava,yakniPointdanRectangle.Mulaisaatinijuga,sayainginmembuatAnda tahu bahwa pointsdanrectangle bukanlah objekobjekgambaryangakan tampildi layar.Keduanyamerupakanvariabelyangmengandungdata,samahalnyadenganint dandouble.Layaknyavariabelvariabellain,keduanyadigunakansecarainternaluntuk mengerjakanperhitunganperhitungan. DefinisidefinisimengenaikelasPointdankelasRectangleberadadalampaketjava.awt, jadikitaharusmengimportkeduanya.
8.2
Paketpaket
Kelaskelas bawaan Java dibagi ke dalam beberapa paket, termasuk paket java.lang yangmengandunghampirsemuakelasyangtelahkitagunakansejauhini.Begitujuga dengan javax.swingyangberisikelaskelasuntukbekerjadenganjendela(window), tombol(button),grafis(graphic),dsb. Untukmenggunakansebuahpaket,Andaharusmengimportnya,inilahyangmenjadi
168
alasan kenapa program yang ada di bagian D.1 dimulai dengan sintaks import javax.swing.*.Tanda'*'mengindikasikanbahwakitainginmengimportsemuakelas yangberadadalampaketSWING.JikaAndamau,Andadapatmenuliskankelaskelas yang Anda inginkan secara eksplisit, tapi sayangnya tidak terlalu menguntungkan. Kelaskelas dalam java.lang sudah diimport secara otomatis. Hal inilah yang menyebabkankenapaprogramprogramyangkitatulissejauhinibelummemerlukan sebuahperintahimport. Semuaperintahimporttampildibagianawaldarisebuahprogram,diluardefinisimilik kelas.
8.3
ObjekTitik(Point)
Dalam pengertian yang paling sederhana, sebuah titik (point) adalah dua angka (koordinat) yang kita anggap/sepakati sebagai sebuah objek tunggal. Dalam notasi matematika, titiktitik ini (points) sering ditulis dalam tanda kurung (parentheses), dengan satu koma yang memisahkan kedua koordinat. Contohnya, (0, 0) yang mengindikasikantitikasal/awal,dan(x,y)yangmengindikasikantitikdilokasixsatuan kekanandanysatuankeatasdenganacuantitikasal(0,0). DalamJava,sebuahtitikdirepresentasikandengansebuahobjekyangdisebutPoint. Untukmembuatsebuahtitikyangbaru,Adaharusmenggunakanperintahnew: Pointblank; blank=newPoint(3,4); Barispertamaadalahcontohdeklarasivariabelyangsudahumumaliaskonvensional: blankmemilikitipedataPoint.Sementarabariskeduaadalahsesuatuyangterlihatlucu; barisinimemanggil(invoke)perintahnew,lalumenentukantipeuntukobjekyangbaru itu, kemudian memberinya argumenargumen. Mungkin ini bukanlah sesuatu yang mengejutkanAndabahwaargumenargumenyangberadadalamtandakurung,(3,4), 169
adalahkoordinatdarititikyangbarukitabuat. Hasildariperintahnewyangbarukitabuatadalahsebuahacuan(reference)bagititik yangbaru.Sayaakanmenjelaskanmasalahacuaninisecaralebihmendalam dalam bagian yang lain. Untuk sekarang, yang lebih penting adalah bahwa variabel blank berisiacuankepadaobjekyangbarusajadibuat.Adacarastandaruntukmenggambar diagramassignmentsepertiini.Lihatgambarberikut:
Sepertibiasa,namavariabelblankmunculdiluarkotaksementaranilainilainyaberada di dalam. Dalam kasus ini, nilai adalah suatu acuan, seperti yang ditunjukkan oleh sebuahdotdananakpanahdalamgambar.Anakpanahitumenunjukkeobjekyang sedangkitaacu. Kotakbesaritumemperlihatkanobjekyangbarusajakitabuatbeserta2nilaiyang beradadidalamnya.xdanyadalahnamadarivariabelvariabelinstan. Jikadisatukan/digabungkan,makasemuakomponen,variabel,nilai,danobjekdalam program tersebut akan disebut dengan state. Diagramdiagram seperti ini yang menunjukkanstatedarisuatuprogramdisebutjugadengandiagramdiagramstate(state diagram).Ketikaprogramberjalan(running),statenyajugaakanberubah.Jadi,Anda harusmenganggapdiagramstatesebagaisebuahsnapshot(tangkapan)darisuatutitik tertentuketikaeksekusisedangterjadi.
8.4
VariabelInstan
setiapobjek,yangmerupakansebuahinstandaritipenyasendiri,memilikisalinaninstan variabelnyasendiri. Halinipersissepertilacikecilyangadadidalamsebuahmobil.Setiapmobiladalah instandaritipemobil,dansetiapmobilmemilikilacikecilnyamasingmasing.Jika AndamenyuruhsayauntukmengambilsesuatudarilacikecildalammobilAnda,maka AndaharusmemberitahusayadahulumobilmanayangmenjadikepunyaanAnda. Mirip dengan analogi di atas, jika Anda ingin membaca sebuah nilai dari sebuah variabelinstan,makaAndaharusmenentukanterlebihdahuluobjekmanayangakan mengambilnilaitersebut.DalamJava,aksiiniakandikerjakandenganmenggunakan perintahnotasidot. Intx=blank.x; Ekspresiblank.xmengandugartipergilahketempatyangdiacuolehobjekblank,lalu ambillahnilaix.Dalamkasusini,kitamengassignnilaitersebutkedalamsebuah variabellokalyaknix.Perhatikanbahwatidakadakonflikyangterjadiantaravariabel lokal x dengan variabel instan x. Fungsi notasi dot dalam kasus ini adalah untuk mengidentifikasidenganpastivariabelmanayangsedangatauakanAndaacu. AndadapatmenggunakannotasidotuntukekspresibahasaJavaapapun,jadibentuk berikutinidianggaplegal. System.out.println(blank.x+","+blank.y); intdistance=blank.x*blank.x+blank.y*blank.y; Barispertamamencetak3,4;sementarabariskeduamenghasilkannilai25.
8.5
ObjekSebagaiParameter
System.out.println("("+p.x+","+p.y+")"); } adalah sebuah metode yang menggunakan sebuah point sebagai argumen lalu mencetaknyadalamformatstandar.JikaAndamemanggilmetodeprintPoint(blank), Anda akan mencetak (3, 4). Sebenarnya, Java mempunyai metode bawaan untuk mencetak Points. Jika Anda memanggil System.out.println(blank) Anda akan mendapatkan java.awt.Point[x=3,y=4] InimerupakanformatstandarJavauntukmencetakmencetaksuatuobjek.Metodeini akanmencetaknamatipe,kemudiandiikutidenganisidariobjektersebut,termasuk namanamadannilainilaidarivariabelinstan. Untukcontohtambahan,kitadapatmenulisulangmetodedistancedaribagian5.2agar iamenggunakanduaPointsebagaiparameterketimbangempatdouble. publicstaticdoubledistance(Pointp1,Pointp2){ doubledx=(double)(p2.xp1.x); doubledy=(double)(p2.yp1.y); returnMath.sqrt(dx*dx+dy*dy); } Typecastdiatassebenarnyatidaklahterlalubermanfaat;sayahanyamenambahkannya sebagaipengingatbahwavariabelinstandalamsebuahPointadalahinteger.
8.6
Rectangle
RectanglememilikisifatyanghampirmiripdenganPoint,kecualivariabel instannya yangberjumlahempat.Keempatvariabelituantaralain;x,y,width,danheight.Selain itu,semuanyasamasaja. Rectanglebox=newRectangle(0,0,100,200); menghasilkan sebuah objek Rectangle baru sekaligus membuat variabel box akan 172
8.7
Objeksebagaitipekembalian(ReturnType)
Andadapatmenulismetodeyangmenghasilkannilaikembalianbertipeobjek.Sebagai contoh, findCenter menggunakan Rectangle sebagai argumen lalu mengembalikan sebuah Point, yang merupakan objek, yang berisi koordinatkoordinat pusat dari Rectangle: publicstaticPointfindCenter(Rectanglebox){ intx=box.x+box.width/2; inty=box.y+box.height/2; returnnewPoint(x,y); } PerhatikanbahwaAndadapatmenggunakan new untukmembuatsebuahobjekbaru, untukkemudianlangsungmenggunakanhasilnyasebagainilaikembalian.
8.8
Objekdapatdiubahubah(Mutable)
Anda dapat mengubahubah isi dari sebuah objek dengan cara membuat sebuah assignmentuntuksalahsatuvariabelinstanyangdimilikinya.Sebagaicontoh,untuk memindahkan sebuah lingkaran tanpa mengubah ukurannya, Anda dapat memodifikasinilaixdany: box.x=box.x+50; box.y=box.y+100; HasilnyadapatAndalihatdalamgambardibawahini: 173
Kitadapatmengambilkodeinilalumengenkapsulasinyadalamsebuahmetode,lalu menggeneralisasinya agar dapat digunakan untuk memindahkan sebuah lingkaran dengannilaiberapapunyangkitamau. publicstaticvoidmoveRect(Rectanglebox,intdx,intdy){ box.x=box.x+dx; box.y=box.y+dy; } Variabeldxdandyakanmemberitahusejauhmanaperpindahanyangtelahterjadipada lingkarandalamsetiaparah.JikaAndamemanggilmetodeini,berartiAndajugatelah mengubahobjekRectangleyangdilewatkansebagaisebuahargumen. Rectanglebox=newRectangle(0,0,100,200); moveRect(box,50,100); System.out.println(box); akanmencetak java.awt.Rectangle[x=50,y=100,width=100,height=200]. Memodifikasiobjekdengancaramelewatkanmerekasebagaiargumenuntuksebuah metodememangdapatmemberikanmanfaat.Namunhalinijugadapatmenimbulkan kesulitan ketika kita hendak melakukan debugging. Kok bisa? Karena terkadang tidaklah terlalujelasbagikitauntukmenentukandengancepatpemanggilanmetode manayangturutmengubahatautidakmengubahmasingmasingargumenyangmereka bawa. Nanti, saya akan membahas beberapa pro dan kontra yang berkaitan dengan teknikpemrogramansepertiini. 174
Untuksaatini,kitasudahdapatmenikmatikemewahanyangtersediadalammetode metodebawaanJava.Termasukdidalamnyatranslate,yangkemampuannyasepadan dengan metode moveRect, meskipun sintaks yang digunakan untuk memanggilnya mungkin agak sedikit berbeda. Ketimbang melewatkan Rectangle sebagai sebuah argumen, kita memanggil translate dalam objek Rectangle kemudian melewatkan variabeldxdandysajasebagaiargumen. box.translate(50,100); PengaruhyangdihasilkanakansamadenganmoveRect.
8.9
Aliasing
Pentinguntukdiingat,ketikaAndamengassignsuatuvariabeldenganobjek,iniberarti Anda sedang mengassign sebuah acuan (reference) untuk sebuah objek. Java mengizinkanAndauntukmembuatlebihdarisatuvariabelyangmengacukepadasatu objekyangsama.Untuklebihjelasnya,perhatikankodeberikutini: Rectanglebox1=newRectangle(0,0,100,200); Rectanglebox2=box1; kodediatasakanmenghasilkandiagramstatesepertiyangtampakdibawahini:
Baikbox1maupunbox2mengacukepadaobjekyangsama.Dengankatalain,objekini memilikiduanama,yaknibox1danbox2.Ketikaseorangindividumemilikiduabuah nama,kitamenyebutnyadenganistilahaliasing.Nah,begitujugadenganobjek. Ketika dua variabel berada dalam status aliasing, semua perubahan yang dapat memengaruhisatuvariabelakanturutmemengaruhivariabellainnya.Contohnya:
175
Barispertamaakanmencetak100,yangmerupakanlebardariRectangleyangdiacu olehbox2.Sementarabariskeduadigunakanuntukmemanggilmetodegrowmelalui box1. Pernyataan ini akan melebarkan/memperluas Rectangle sebanyak 50 pixel ke segala arah (silahkan membaca dokumentasinya agar lebih jelas). Perubahan yang terjadiditunjukkanolehgambardibawahini:
Melaluigambarini,seharusnyaAndasudahdapatmemahami,bahwaperubahanapapun yangterjadipadabox1jugaturutmemengaruhibox2.Olehkarenaitulah,nilaiyang dicetakolehpernyataanpadabarisketigaadalah200,sebagailebardarihasilperluasan lingkaran. (Sebagai pertimbangan, Java juga mengizinkan nilai negatif sebagai koordinatRectangle) Darikodesederhanadiatas,Andamungkinakanlangsungmenyimpulkanbahwakode yangmenerapkanprinsipaliasingjustrudapatmerepotkankitasendiri.Apalagikalau sudahmasukkedalamurusandebugging.Untukitulah,sebaiknyaAndamenghindari penggunaanteknikini,ataugunakaniadengansehatihatimungkin.
8.10 Null
KetikaAndamembuatsebuahvariabelobjek,AndaharusingatbahwaAndasedang mengacukepadasuatuobjek.JikaAndabelummembuatvariabeltersebutmengacu kepadasuatuobjek,makanilaidarivariabelituakansamadengannull.nulladalahnilai yangkhusus(jugasebuahkeyword)dalamJavayangberartitidakadaobjek. Pendeklarasianbentuk Pointblank;
176
akansamadenganinisialisasiberiktuini: Pointblank=null;
Diagramstatedarideklarasidiatasdapatdilihatmelaluigambardibawahini:Nilainull direpresentasikandengansebuahdottanpaanakpanah. Jika Anda mecoba untuk menggunakan objek yang berstatus null, entah dengan mengaksesnyamelaluivariabelinstanataumemanggilnyamelaluisebuahmetode,Anda akan mendapatkan sebuah pesan berbunyi, NullPointerException. Sistem akan menampilkansebuahpesanerrorlalumenghentikanprogramitu. Pointblank=null; intx=blank.x;//NullPointerException blank.translate(50,50);//NullPointerException Di sisi lain,adalahlegaldalam Javauntukmelewatkan sebuahobjek berstatusnull sebagaisebuahargumenataumenerimasalahsatunyasebagaisebuahnilaikembalian. Faktanya,memangdemikianlahadanya.ParapenggunaJavaterbiasamengaplikasikan konsep ini untuk merepresentasikan sebuah himpunan kosong atau untuk menginformasikansebuahkeadaanerror.
8.11 GarbageCollection
Dalambagian8.9kitatelahberbicaramengenaiapayangakanterjadijikalebihdari satu variabelmengacukepadasatuobjekyangsama.Lalusekarang,apayangakan terjadi jikatidakadasatupunvariabelyangmengacukepadasuatuobjek?Sebagai contoh: Pointblank=newPoint(3,4); blank=null;
177
Jikatidakadavariabelyangmengacukepadasebuahobjek,makatidakakanadayang dapat membaca (read) atau menulisi (write) objek ini dengan nilai apa pun, atau memanggilsebuahmetodemelaluiobjekini.Walaupunbegitu,objeksepertiinitetap eksisdalammemori.Sebenarnya,kitabisasajamenyimpanobjekinidalammemori, tapi hal ini hanya akan membuangbuang ruang (space). Oleh karena itulah, selagi programAndaberjalan,sistemJavaakanmencariobjekobjekyangtidakterpakaiini secaraberkala(periodically),untukkemudianmengaturnya.Prosesinilahyangdisebut dengangarbagecollection.Walhasil,ruangmemoriyangtadinyadipakaiolehobjekini akandapatdigunakankembalisebagaibagiandariobjekyangbaru. Andatidakperlumelakukanapapununtukmembuatprosesgarbagecollectionbekerja. Lagipula,umumnyaAndamemangtidakakanmemerhatikannya.
8.12 ObjekdanPrimitif
AdaduajenistipedatadalamJava,tipedataprimitifdantipedataobjek.Tipeprimitif, sepertiintdanbooleandiawalidenganhurufkecil;sementaratipeobjekdiawalidengan hurufkapital.Perbedaaninisangatbermanfaatkarenadapatmengingatkankitakepada beberapaperbedaanantarakeduanya.
178
mendapatkan ruang penyimpanan untuk nilai primitif. Ketika Anda mendeklarasikan variabel bertipe data objek, Anda akan mendapatkan ruang memorisebagaiacuan(reference)kepadasebuahobjek.AgarobjekyangAnda buatmemilikiruang,Andaharusmenggunakanperintahnew.
VariabelvariabelprimitifdiisolasidenganbaikolehJava.Maksudpernyataan iniadalahbahwaAndatidakdapatmelakukanapapunmelaluisebuahmetode untukmengubahvariabellainyangberadadalammetodelain.Variabelvariabel objekmenjadiagaksulitdanmembingungkanuntukdigunakankarenamereka tidak diisolasi sebaik variabel bertipe primitif. Jika Anda melewatkan suatu referensi kepada sebuah objek sebagai sebuah argumen, maka metode yang Andapanggildapatmengubahobjektersebut.Keadaanyangsamajugaberlaku ketikaAndamemanggilsebuahmetodemelaluisuatuobjek.Tetapitentusaja, halinisebenarnyajugadapatbermanfaatuntukAnda,asalkanAndahatihati ketikamenggunakannya.
Adasatuperbedaanlagiantaratipedataprimitifdengantipedataobjek.Andatidak dapatmenambahkantipedataprimitifbarukedalambahasaJava(kecualikalauAnda termasukdalamanggotakomitestandardisasiJavamilikSunMicrosystem),tapiAnda dapat membuat tipe objek yang baru! Caranya? Kita akan melihatnya di bagian berikutnya.
179
8.13 DaftarKataKata
Istilah Arti Sebuahkumpulandarikelaskelas(classes).Kelaskelas paket(package) yangdibawa(builtin)olehJavadikeloladalambentuk paketpaket. AWT Abstract Window Toolkit, salah satu paket terbesar dalamJava. Sebuah contoh dari suatu kategori/golongan. Kucing instan(instance) sayaadalahsuatuinstandari(baca:yangtermasukke dalam golongan) keluarga kucing. Semua objek adalahinstandaribeberapakelas. Salah satu itemitem data yang membentuk sebuah variabelinstan objek.Setiapobjek(instan)memilikisalinanvariabel variabelinstanuntukkelasnyamasingmasing. Sebuah nilai yang mengindikasi sebuah objek. Dalam acuan(reference) sebuah diagram state, suatu acuan diwakili dengan gambaranakpanah. aliasing Suatukondisidimanaduaataulebihvariabelmengacu keobjekyangsama. Suatu proses untuk mencari objekobjek yang tidak garbagecollection punyaacuanuntukkemudianmengelolakembaliruang memoriyangtelahdipakainya. Sebuahdeskripsilengkapdarisemuavariabeldanobjek state sekaligus nilainilai yang dikandungnya pada suatu waktu tertentu selama eksekusi program sedang berlangsung. 180
8.14 Latihan
Latihan8.1 a) Untukprogramdibawahini,gambarlahsebuahdiagramstackyangmenunjukkan variabelvariabellokaldanparameterparameterdarimaindanfred,lalutunjukkan suatuobjekyangdiacuolehvariabelvariabeltersebut. b) Apakahoutputyangdihasilkanolehprogramberikutini? publicstaticvoidmain(String[]args) { intx=5; Pointblank=newPoint(1,2); System.out.println(fred(x,blank)); System.out.println(x); System.out.println(blank.x); System.out.println(blank.y); } publicstaticintfred(intx,Pointp) { x=x+7; returnx+p.x+p.y; }
181
Tujuan utama dari latihan ini adalah untuk memastikan bahwa Anda benarbenar memahamimekanismeuntukmelewatkanobjeksebagaiparameter. Latihan8.2 a) Untuk program berikut ini, gambarlah sebuah diagram stack yang menunjukkan keadaan dari program beberapa saat sebelum metode distance dikembalikan. MasukkankedalamgambarAndaitusemuavariabel,parameter, danobjekyang diacuolehvariabelvariabeltersebut. b) Outputapakahyangdihasilkanolehprogramberikutini? public static double distance (Point p1, Point p2) { intdx=p1.xp2.x; intdy=p1.yp2.y; returnMath.sqrt(dx*dx+dy*dy); } publicstaticPointfindCenter(Rectanglebox){ intx=box.x+box.width/2; inty=box.y+box.height/2; returnnewPoint(x,y); } publicstaticvoidmain(String[]args){ Pointblank=newPoint(5,8); Rectanglerect=newRectangle(0,2,4,4); Pointcenter=findCenter(rect); doubledist=distance(center,blank); System.out.println(dist); } 182
Latihan8.3 MetodegrowadalahbagiandarikelasRectangle.Berikutinimerupakandikumentasi mengenaigrow(diambildarisitusSun): publicvoidgrow(inth,intv) Growstherectanglebothhorizontallyand vertically. This method modifies the rectangle so that it is h units larger on both the left and right side, and v unitslargeratboththetopandbottom. The new rectangle has (x h, y v) as its top left corner, a width of width + 2h, and a height of height+2v. Jikanilainegatif a) Outputapakahyangdihasilkanolehprogramberikutini? b) Gambarkansebuahdiagramstateyangmenunjukkankeadaandariprogramsesaat sebelummainberakhir.MasukkankedalamgambarAndatersebutsemuavariabel danobjekobjekyangdiacunya. c) Padabagianakhirdarimain,apakahp1danp2termasukaliasing?Mengapaatau mengapatidak? publicstaticvoidprintPoint(Pointp){ System.out.println("("+p.x+","+p.y+ ")");
183
} publicstaticPointfindCenter(Rectanglebox){ intx=box.x+box.width/2; inty=box.y+box.height/2; returnnewPoint(x,y); } publicstaticvoidmain(String[]args){ Rectanglebox1=newRectangle(2,4,7,9); Pointp1=findCenter(box1); printPoint(p1); box1.grow(1,1); Pointp2=findCenter(box1); printPoint(p2); } Latihan8.4 Mungkin sekarang Anda sudah benarbenar bosan dengan metode faktorial, tapi sayangnyakitaakanmembuatsatuversilagidarimetodeini. a) BuatlahsebuahprogrambarudengannamaBig.javalalumulailahdenganmenulis sebuahversiiteratifdarifactorial. b) Cetaklahsebuahtabelintegerdari0s.d.30bersamafaktorialmereka.Ketikasampai ke nilai 15an, Anda mungkin akan mendapati bahwa jawaban Anda sepertinya sudahtidaktepatlagi.Cobaperiksa!Mengapabegitu? c) BigInteger adalah metode bawaan Java yang dapat merepresentasikan bilangan
184
bilangan integer. Tidak ada batasatas kecuali ukuran memori dan kecepatan pemrosesanitusendiri.CetaklahdokumentasiuntukkelasBigIntegeryangterdapat dalampaketjava.math,lalubacalah! d) Ada beberapa cara untuk membuat metode BigInteger, tapi yang saya rekomendasikan adalah dengan menggunakan valueOf. Kode berikut ini akan mengkonversikansebuahintegerkebentukmetodeBigInteger: intx=17; BigIntegerbig=BigInteger.valueOf(x); Tulislahkodeini!Lalucobalahbeberapakasussederhana,sepertimembuatsebuah BigInteger kemudian mencetaknya. Perhatikan bahwa metode println sudah mengetahui cara untuk mencetak BigInteger! Jangan lupa untuk menambahkan importjava.math.BigIntegerdiawalprogramAnda. e) Sayangnya, karena BigInteger bukanlah tipe primitif, kita jadi tidak dapat menggunakan operator matematika biasa untuknya. Sebaliknya, kita akan menggunakan metode objek seperti add. Untuk menambah dua BigInteger, Anda harusmemanggiladdmelaluisalahsatuobjekdanmelewatkanobjeklainnyasebagai argumen.Sebagaicontoh: BigIntegersmall=BigInteger.valueOf(17); BigIntegerbig=BigInteger.valueOf(1700000000); BigIntegertotal=small.add(big); Cobalahbeberapametodelainnya,sepertimultiplydanpow. f) Konversikanlah metode factorial sehingga ia dapat melakukan penghitungan menggunakan BigInteger, lalu mengembalikan BigInteger sebagai hasilnya. Anda tidak perlu menghiraukan parameternya karena tipe data yang akan digunakan tetaplahberupainteger.
185
g) Cobalahmencetaktabellagidenganmetodefactorialyangtelahandamodifikasi. Benarkahhasilnyauntukangkadiatas30?Sampaiseberapabesar(baca:angkanya) Anda dapat mempertahankan ketepatan ini? Saya telah menghitung faktorial dari semuaangkamulaidari0s.d.999.Namunkarenamesinsayaterlalulambat,saya jadi perlu waktu yang agak lama. Angka terakhir, 999!, mempunyai 2565 digit. BagaimanadenganAnda? Latihan8.5 Banyak algoritmaalgoritma enkripsi sangat bergantung kepada kemampuan untuk menaikkannilaiintegeryangbesarkebentukintegerberpangkat.Berikutiniadalah sebuahmetodeyangmengimplementasikansebuahalgoritmacepatuntukpemangkatan (exponentiation)integer. publicstaticintpow(intx,intn){ if(n==0)return1; //findxtothen/2recursively intt=pow(x,n/2); //ifniseven,theresultistsquared //ifnisodd,theresultistsquaredtimesx if(n%2==0){ returnt*t; }else{ returnt*t*x; } } Masalahyangmunculdalammetodeiniadalahbahwaiahanyabekerjadenganbenar 186
jikahasilyangdidapatkankurangdari2miliar.Tulisulanglahmetodeinisehingga hasilnya merupakan bentuk BigInteger. Meskipun begitu, parameterparamater yang digunakanharuslahtetapberupainteger. Anda diizinkan menggunakan metode add dan multiply milik BigInteger, tapi tidak denganmetodepow,karenametodeinibisajadijustruakanmerusak'keceriaan'Anda.
187
SetiapkaliAndamenulissebuahdefinisiuntukkelas,Andasebenarnyatelahmembuat sebuahtipeobjekbarudengannamayangsamadengannamakelasAnda.Kembalike bagian 1.5, ketikakita mendefinisikan sebuah kelas bernama Hello, pada saat yang sama (tanpa perlu Anda sadari) kita juga membuat sebuahtipe objek dengan nama Hello.KitatidakmembuatvariabelapapununtuktipeHello,tidakjugamenggunakan perintahnewuntukmembuatobjekobjekHello,tapikitasudahberhasilmelakukannya! Contoh di atas agak tidak masuk akal, karena kita pada dasarnya memang tidak bermaksuduntukmembuatobjekHello.Lagipula,masihtidakjelasapamanfaatnya untukkitakalaumemangkitabenarbenartelahmembuatnya.Dalambabini, kita
Mendefinisikan sebuah kelas baru akan menyebabkan 'lahirnya' sebuah tipe objekbarudengannamayangsama.
Setiap objek merupakan milik beberapa objek sekaligus; oleh karena itulah, setiapobjekjugamerupakaninstandaribeberapakelas.
Semuametodeyangberoperasidalamsebuahtipeakanmasukdalamdefinisi kelasuntuktipetersebut.
Berikutinimerupakanisuisusintaksmengenaidefinisidefinisikelas:
Andabiasanyameletakkansatudefinisikelasdalamsetiapfile,dannamafile tersebut haruslah sama dengan nama kelas yang Anda buat dengan ekstensi .java. Sebagai contoh, kelas Time didefinisikan dalam sebuah file bernama Timed.Java.
Dalamprogrammanapun,sebuahkelasdirancanguntukmenjadikelasstartup (startupclass).Kelasiniharusmengandungsebuahmetodedengannamamain, yang akan menjadi tempat dimana eksekusi program dimulai. Kelas lain diizinkanuntukmemilikimetodemain,tapiiatidakakandieksekusi.
Dengan topiktopik di atas, sekarang kita akan melihat sebuah contoh kelas yang merupakanhasilbuatansendiri(userdefinedtype),yakniTime.
9.2
Time
Tujuan utama yang mendasari pembuatan sebuah tipe objek baru adalah untuk mengambilbeberapadatayangsalingberhubunganlalumengenkaspsulasimerekake dalam sebuah objek yang dapat dimanipulasi (dilewatkan sebagai sebuah argumen, beroperasidengansuatumetode)sebagaisebuahunittunggal.Sebelumnyakitasemua sudahmelihatduatipebawaanJavasepertiini,yaituPointdanRectangle. Contohlainnya,yangakankitaimpelementasikansendiriadalahTime.Tipeobjekini akan kitagunakanuntukmerekamwaktudalamsatuhari.Beberapainformasiyang 189
menyusun'sebuah'waktuantaralain;jam,menitdandetik.Karenasetiapobjekwaktu akanberisidataini,kitamemerlukanvariabelinstanuntukmenyimpandatatersebut. Langkahpertamaadalahmenentukantipedatayangcocokuntukvariabelyangakan kitagunakan.Untukvariabelhourdanminute,kitasebaiknyamenggunakaninteger. Untukmembuatprosesinilebihmenyenangkan,marikitasimpandataseconddalam variabelbertipedoubleagarnantinyadapatmerekamdetikdetikyang'kecil'. Variabelinstanakandideklarasikandiawaldefinisikelas,diluarsemuadefinisimetode yangada,sepertiinibentuknya: classTime{ inthour,minute; doublesecond; } LampirankodediatastermasukdefinisikelasyanglegaldalamJava.Diagramstate untukobjekTimeakantampaksebagaiberikut:
Setalah mendeklarasikan variabel instan, langkah selanjutnya adalah mendefinisikan/menentukansebuahkonstruktoruntukkelasyangbaru. Fungsi utamadarikonstruktor adalahuntukmenginisialisasivariabelinstan.Sintaks untuk membuat konstruktor sama dengan yang digunakan untuk membuat metode metodebiasa,tapidengantigapengecualian:
BerikutiniadalahcontohkelasTime: publicTime(){
190
this.hour=0; this.minute=0; this.second=0.0; } PerhatikanbahwatidakadaapaapadiantarakeywordpublicdanTime(yangbiasanya terdapattipedatapengembaliandiantaranya).Inilahsalahsatucarayangdigunakan olehkita(juga compiler)untukmenyatakanbahwalampirankodediatasmerupakan sebuahkonstruktor. Konstruktor di atas tidak menggunakan satu argumen pun, sebagaimana yang diindikasikanolehtandakurungyangkosong;().Setiapbarisyangterkandungdalam konstruktorakanmenginisialisasisebuahvariabelinstandengannilaidefaultyangkita buatsendiri(dalamkasusini,kitamenginisialisasiTimedenganwaktutepatdisaat tengahmalam,yaitu0,0,dan0.0).keywordthismerupakankatatercadangkhususyang merupakan nama dari objek yang sedang kita buat. Anda dapat menggunakan this seperti anda menggunakan namanama objek lainnya. Sebagai contoh, Anda dapat membacadanmenulisvariabelinstandenganthis,laluAndajugadapatmelewatkanthis sebagaiargumenkepadametodelainnya. TetapiAndatidakperlumendeklarasikanthisataumenggunakanperintahnewuntuk membuatnya. Kenyataannya, Anda bahkan tidak diizinkan untuk mengassignnya dengansesuatuapapun.thismerupakanproduksistemJavasecaraotomatis;yangharus Andalakukanhanyalahmenyimpannilainilaikedalamvariabelinstanmiliknya.Itu saja! Suatubentukerroryangseringdilakukanolehparapemrogramketikamenulissebuah konstruktor yaitu ketika mereka meletakkan perintah return di akhir kode untuk konstruktormereka.Hindarikesalahansepertiini!
191
9.4
KonstruktorLagi
Konstruktorkonstruktor dalam Javajugadapat berstatus overloadingsepertimetode pada lazimnya. Akibatnya, Anda dapat menyediakan beberapa konstruktor sekaligus dalamsebuahtipeobjekdenganparameterparameteryangberbeda.Javamengetahui konstruktormanayangdipanggildengancaramencocokkanargumenyangdigunakan oleh perintah new dengan parameterparameter yang digunakan oleh konstruktor konstruktor. AdalahsesuatuyangbiasadalamJavajikaterdapatsebuahdefinisikelasyangselain mengandungkonstruktoryangtidakmempunyaisatuargumenpun(sepertiditunjukkan di atas), ia juga mengandung sebuah konstruktor yang menggunakan beberapa parametersekaligusyangidentikdenganvariabelvariabelinstanmiliknya.Contohnya: publicTime(inthour,intminute,doublesecond){ this.hour=hour; this.minute=minute; this.second=second; } Namadantipeparamateryangdigunakanakansamapersisdengannamadantipedari variabelinstan.Semuakonstruktorbertugasuntukmenyalininformasidariparameter parameteritukedalamvariabelvariabelinstan. Jika AndakembalidanmelihatdokumentasiuntukPointdanRectangle,Andaakan melihat bahwa kedua kelas tersebut menyediakan konstruktor seperti ini. Status overloading dalam konstruktor dapat memberikan fleksibilitas bagi Anda untuk membuatsebuahobjekterlebihdahululalumengisikekurangankekurangannya,atau Andadapatmengumpulkansemuainformasisebelummembuatsuatuobjekyangbenar benarsesuaidengankeinginanAnda. 192
Sejauh ini, apa yang sedang kita lakukan mungkin tidaklah terlalu menarik, dan memang demikianlah adanya. Menulis konstruktor adalah pekerjaan yang membosankan, maklum saja, proses ini memang dapat dianalogikan seperti proses mekanis(mereparasimesin).SekalisajaAndatelahmampumenulisduakonstruktor sekaligus, Anda akan sadar bahwa tanpa berkedip pun Anda sebenarnya tetap bisa membuatnya.Cukupdenganmemperhatikandaftarvariabelvariabelinstannyasaja.
9.5
MembuatSebuahObjekyangBaru
Meskipunkonstruktorkonstruktorinitampaksepertisebuahmetode,Andatetaptidak akan pernah bisa memanggilnya secara langsung. Sebaliknya, ketika Anda menggunakanperintahnew,sistemakanmengalokasikanruangmemoriuntukobjek yangbarulalumemanggilkonstruktorAndauntukmenginisialisasivariabelvariabel instannya. Program berikut ini memperlihatkan kepada kita dua cara untuk membuat dan menginisialisasiobjekTime: classTime{ inthour,minute; doublesecond; publicTime(){ this.hour=0; this.minute=0; this.second=0.0; } publicTime(inthour,intminute,double second) { 193
this.hour=hour; this.minute=minute; this.second=second; } publicstaticvoidmain(String[]args){ //onewaytocreateandinitializeaTime object Timet1=newTime(); t1.hour=11; t1.minute=8; t1.second=3.14159; System.out.println(t1); //anotherwaytodothesamething Timet2=newTime(11,8,3.14159); System.out.println(t2); } }
SebagailatihanuntukAnda,cobalahpahamilalutentukanbagaimanaaliraneksekusi programini. Dalam metode main, ketika kali pertama kita memanggil perintah new, kita tidak memberikansatuargumenpun,akibatnya,Javaakanmemanggilkonstruktorpertama dari kelasTimediatas.Beberapabarisberikutnyamengassignnilainilaikesetiap variabelvariabelinstan. 194
Pada kesempatan kedua ketika kita memanggil perintah new, kita memberikan argumenargumen yang cocok dengan parameterparameter dari konstruktor kedua. Carapenginisialisasianvariabelinstansepertiinimungkinlebihjelas(danefisien),tapi jugadapatlebihmenyulitkanuntukdibaca.Halinibisajadidisebabkankarenatidak jelasnyanilainilaiapayangakandiassignkevariabelinstanyangmana.
9.6
MencetakSebuahObjek
Outputdariprogramdiatasadalah: Time@80cc7c0 Time@80cc807 KetikaJavamencetaknilaidarisebuahtipeobjekbuatanpengguna(userdefinedobject type),yangakandicetaknyaadalahnamadaritipeobjektersebutbesertasuatukode heksadesimal(basis16)yangunikuntuksetiapobjek.Kodeinimemangtidakartinya; kenyataannya,hasilinibisabervariasidiantarasatumesindenganmesinlainnyaatau bahkandiantarawaktupemrosesanyangsatudenganwaktupemrosesanyanglainnya. Meskipunbegitu,kitamasihtetapdapatmemanfaatkannyauntukdebugging,misalnya untuk kasus dimana kita tetap ingin mengawasi keberadaan suatu objek secara individual. Untukmencetakobjekyangmenghasilkanpesanyanglebihmanusiawi(baca:dapat dimengerti) bagi pengguna, Anda biasanya ingin menulis sebuah metode seperti printTime: publicstaticvoidprintTime(Timet){ System.out.println(t.hour+":"+t.minute + 1. ":"+t.second);
195
} BandingkanlahmetodeinidenganmetodeprintTimeyangadadibagian3.10. Output metode ini, jika kita melewatkan t1 atau t2 sebagai argumen adalah 11:8:3.14159.Meskipunbentuksepertiinikitaanggapsebagaisebuahpenunjukwaktu, tapiiabelumlahdapatdikategorikankedalambentukstandaryangsudahkitakenal. Sebagaicontoh,jikaangkamenitataudetikkurangdari10,makakitamengharapkan adanyaawalanberupaangka0yangberfungsisebagaipenjagatempat(placekeeper). Selain itu, kita mungkin ingin membuang angkaangkayang termasuk dalamangka desimal/pecahandaridetik.Dengankatalain,kitainginsesuatuyangtampakseperti 11:08:03. Dalamlingkunganbahasabahasapemrogramanlainnya,biasanyasudahterdapatcara sederhanauntukmengendalikanformatoutputyangberupaangkaangka.Namundalam Java,tidakadacarasepertiitu. Java menyediakan tools yang sangat bagus untuk mencetak sesuatu yang sudah memiliki bentuk standar (formatted things) seperti waktu atau tanggal, juga untuk menginterpretasikan inputinput terformat (formatted input). Sayangnya, tools ini tidaklahterlalumudahuntukdigunakan,jadisayatidakakanmembahasnyadidalam bukuini.TetapijikaAndabenarbenaringinmenggunakannya,silahkanmelihatlihat dokumentasimengenaikelasDatedalampaketjava.util.
9.7OperasiPadaObjek
Meskipunkitatidakdapatmencetakwaktudalamformatyangoptimal,kitamasihdapat menulis sebuah metode yang bisa memanipulasi objek Time. Dalam bagianbagian berikutnya, saya akan menunjukkan beberapa antarmuka (interface) yang mungkin dapat digunakan untuk metodemetode yang beroperasi melalui objekobjek. Untuk 196
beberapaoperasi,Andamempunyaibeberapapilihanantarmukayangbisadigunakan, jadiAndaharusmempertimbangkansendiriprodankontrauntuksetiappilihan:
purefunction:menggunakanobjekobjek/primitifsebagaiargumentetapitidak memodifikasiobjek. Nilai kembalian berupa primitif atau sebuah objek baru yangdibuatdidalammetodetersebut.
9.8
Fungsifungsimurni
Sebuahmetodedianggapsebagaifungsimurnijikahasilnyahanyabergantungkepada argumenargumen,danpadasaatyangbersamaandiatidakmemberikanefeksamping; sepertimemodifikasisebuahargumenataumencetaksesuatu.Satusatunyahasildari melakukan pemanggilan terhadap sebuah fungsi murni adalah nilai kembalian itu sendiri.
Salah satu contohnya adalah after, yang membandingkan dua buah waktu, lalu mengembalikan nilai bertipe boolean yang mengindikasikan apakah operan pertama beradadibelakangoperankedua: public static boolean after (Time time1, Time time2){ if(time1.hour>time2.hour)returntrue; if(time1.hour<time2.hour)returnfalse; if(time1.minute>time2.minute)returntrue; 197
Apayangakandihasilkanolehmetodeinijikakeduawaktuadalahsama?Apakahhasil tersebutmerupakanhasilyangtepatdansesuaidenganapayangkitaharapkandari metode ini? Jika Anda menulis dokumentasi untuk metode ini, maukah Anda menyebutkankasustersebutsecaraspesifik? Contoh kedua adalah addTime, yang mengkalkulasi jumlah dari dua buah waktu. Sebagaicontoh,jikasekarangwaktumenunjukkan9:14:30,danpemanggangrotiAnda membutuhkan 3 jam lebih 35 menit, Anda dapat menggunakan addTime untuk menentukankapanrotiAndaakanselesaidipanggang: publicstaticTimeaddTime(Timet1,Timet2){ Timesum=newTime(); sum.hour=t1.hour+t2.hour; sum.minute=t1.minute+t2.minute; sum.second=t1.second+t2.second; returnsum; } Meskipun metode ini mengembalikan nilai yang berupa objek waktu, ia bukanlah sebuahkonstruktor.Andaharuskembalilagiuntukmembandingkansintaksdarimetode sepertiinidengansintakssebuahkonstruktor.Mengapa?Karenakitaseringkalimenjadi terlalumudahuntukkebingungan. Berikutiniadalahsebuahcontohmengenaibagaimanacaramenggunakanmetodeini. 198
Jika currentTime berisikan waktu saat ini, sementara breadTime mengandung total waktu yang dibutuhkan oleh pembuatroti Anda untuk membuat roti yang Anda inginkan, maka Anda harus menggunakan addTime untuk menentukan kapan roti tersebutakanselesaidibuat. TimecurrentTime=newTime(9,14,30.0); TimebreadTime=newTime(3,35,0.0); TimedoneTime=addTime(currentTime,breadTime); printTime(doneTime); Outputdariprograminiadalah12:49:30.0,yangberartisesuaidenganapayangkita inginkan.Namundisisilain,adakasuskasustertentudimanahasilyangdikeluarkan ternyatatidaksesuai.BisakahAndamenunjukkansalahsatunya? Masalahnyaadalahbahwametodeiniternyatatetapmenjumlahkandanmenampilkan nilai detik dan menit meskipun nilai keduanya telah melampaui angka 60. Untuk mengatasinya,kitaharusberupayaagarjumlahdetiksetelahangka60bisaditambahkan kepada nilai menit (+1 menit). Begitu juga dengan jumlah menit, setiap menembus angka60,nilaimenittersebutakanditambahkankedalamjam(+1jam). Kodeberikutinimerupakanperbaikandarikodediatas: publicstaticTimeaddTime(Timet1,Timet2){ Timesum=newTime(); sum.hour=t1.hour+t2.hour; sum.minute=t1.minute+t2.minute; sum.second=t1.second+t2.second; if(sum.second>=60.0){ sum.second=60.0; sum.minute+=1; 199
} if(sum.minute>=60){ sum.minute=60; sum.hour+=1; } returnsum; } Meskipunkodediatassudahbenar,tapiiaakanmenjadisemakinkompleks.Nanti,saya akan menunjukkan sebuah pendekatan alternatif yang lebih singkat untuk menyelesaikanmasalahmasalahsepertiini. Kodediatasmenampilkanduaoperatoryangbelumkitalihatsebelumnya,yakni'+=' dan'='.Keduaoperatorinimemberikancarayangjelasuntukmenaikkan(increment) ataumenurunkan(decrement)nilaivariabelvariabel.Keduanyahampirsamadengan' ++'dan''kecualibahwa: 1. Keduanyadapatdigunakanuntukoperasivariabelbertipedouble,selainuntuk integer. 2. Derajatkenaikanataupenurunantidakharus1.Pernyataan sum.second=60.0;samadengansum.second=sum.second60;
9.9
Modifier
Untukmencontohkansuatumodifier,perhatikanlahmetodeincrementberikut!Metode ini menambahkan nilai detik ke dalam objek Time. Lagilagi, bentuk mentah dari metodeiniakantampaksebagaiberikut: public static void increment secs){ 200 (Time time, double
time.second+=secs; if(time.second>=60.0){ time.second=60.0; time.minute+=1; } if(time.minute>=60){ time.minute=60; time.hour+=1; } } Barispertamamengerjakanoperasidasar; remainder (nilaipengingat)bekerjadengan carayangsamasepertipadakasusyangsudahkitalihatsebelumnya. Sudahbenarkahmetodeini?Apayangterjadijikaargumensecslebihbesardaripada 60?Dalamkasusini,tidakcukupmenguranginilai60sebanyaksatukalisaja.Kita harus terus mengurangi 60 sampai second bernilai kurang dari 60. kita dapat melakukannyadenganhanyamenggantiperintahifdenganwhile: public static void increment secs){ time.second+=secs; while(time.second>=60.0){ time.second=60.0; time.minute+=1; } (Time time, double
201
9.10 FillinMethods
UmumnyaAndaakanjarangsekalimenemuimetodesepertiaddTimeditulisdengan antar muka yang berbeda (dari segi argumen dan nilai kembaliannya). Ketimbang membuat sebuah objek baru setiap kali addTime dipanggil, kita bisa menyuruh si pemanggil(thecaller)untukmenyediakanobjek'kosong'sebagaitempatbagiaddTime untukmenyimpanhasilnya.Bandingkankodeberikutinidengankodesebelumnya: public static void addTimeFill Timesum){ sum.hour=t1.hour+t2.hour; sum.minute=t1.minute+t2.minute; sum.second=t1.second+t2.second; if(sum.second>=60.0){ sum.second=60.0; sum.minute+=1; } if(sum.minute>=60){ sum.minute=60; 202 (Time t1, Time t2,
sum.hour+=1; } } Satu keuntungan dari pendekatan seperti ini adalah bahwa si pemanggil memiliki kesempatan/opsi untuk menggunakan objek yang sama secara berulangulang untuk melakukanoperasipenjumlahanyangberuntun.Pendekataninimungkinsedikitlebih efisien, meskipun dapat membingungkan juga ketika malah menyebabkan error. Di dalamduniapemrograman,banyakyanglebihmemilihuntukmenghabiskanwaktunya demi sebuah program dengan run time yang pendek (baca: cepat) ketimbang menghabiskanwaktunyauntukmendebugkodeprogramyangpanjang.
9.11 Manayangterbaik?
Semuayangdapatdilakukandenganmenggunakanmodifierdanfillinmethod dapat jugadikerjakanmenggunakanfungsimurni.Dalamkenyataannya,adasebuahbahasa pemrograman, yang disebut sebagai bahasa pemrograman fungsional, yang hanya mengizinkan penggunaan fungsifungsi murni saja. Beberapa pemrogram percaya bahwaprogramyangdibangundenganmenggunakanfungsimurniakanlebihcepat untukdikembangkandanlebihkecilrisikoerrornyaketimbangprogramyangdibangun denganmenggunakanmodifier.Meskipunbegitu,tetapadasaatsaatdimanamodifier lebihsesuaiuntukditerapkan,dansaatsaatdimanaprogramfungsionalmenjaditidak efisien. Secara umum, saya merekomendasikan Anda untuk menulis fungsi murni saja di manapunAndaberkesempatanuntukmenulisnya,lalubergantikemodifierketikaAnda melihatkeuntunganbesardidalamnya.Pendekatansepertiinilahyangmungkindisebut denganteknikpemrogramanfungsional. 203
9.12 Pengembangansecarabertahapvsperencanaan
Dalam bab ini saya telah menunjukkan sebuah pendekatan untuk mengembangkan sebuah program yang saya sendiri menyebutnya sebagai rapid prototyping with iterative improvement. Dalam tiap kasusnya, saya selalu menuliskan satu bentuk mentah (atau prototipe) yang berfungsi untuk mengerjakan kalkulasi dasar, lalu mengujinya dalam beberapa kasus, untuk kemudian langsung memperbaiki kesalahan/kelemahanyangterdapatdidalamnya. Walaupunefektif,pendekataninijugadapatmenyebabkanlahirnyakodeyangtidak perlusekaligusmembingungkankarenadigunakanuntukmenyelesaikanbanyakkasus khususjugatidakdapatdipercaya(unreliable)karenaAndasendirimasihbelum bisayakinapakahAndatelahmenemukansemuaerroryangada. Alternatifyangadadiantaranyaadalahhighlevelprogramming(pemrogramantingkat tinggi).Dalamteknikini,Andaharusbenarbenarmengandalkan deepthinking Anda terhadap suatu kasus. Untuk kasus Time di atas, deepthinking ini berarti Anda menganggapbahwaTimemerupakanangkatigadigitdalambasis60!Artinya,second adalahkolomsatuan,minuteadalahkolom60an,laluhouradalahkolom3600 an. KetikakitamenulisaddTimedanincrement,sebenarnyakitajugasedangmengerjakan penjumlahandalambasis60.Inilahyangmenjadipenyebabsehinggakitamemerlukan carrydarisatukolomkekolomberikutnya. Dus,pendekatanalternatifyangakankitagunakanuntukmenyelesaikansemuamasalah iniadalahdengancaramengkonversikanTimekebentukdouble.Halinikitalakukan karenasebuahfaktabahwakomputermemangsudahmengerticaramengoperasikan aritmetika untuk bentuk double. Berikut ini adalah sebuah metode yang mengkonversikanobjekTimekebentukdouble: 204
publicstaticdoubleconvertToSeconds(Timet){ intminutes=t.hour*60+t.minute; doubleseconds=minutes*60+t.second; returnseconds; } Sekarang,apayangperlukitakerjakanadalahmenemukancarauntukmengubahbentuk double ke bentuk Time. Sebenarnya kita bisa saja menulis sebuah metode untuk melakukannya,tapiakanlebihmasukakaljikakitamenuliskannyasebagaikonstruktor ketiga: publicTime(doublesecs){ this.hour=(int)(secs/3600.0); secs=this.hour*3600.0; this.minute=(int)(secs/60.0); secs=this.minute*60; this.second=secs; } Konstruktorinimemangtampaksedikitberbedadenganyanglainnya,mungkinkarena iamelibatkansejumlahkalkulasidanassignmentterhadapvariabelvariabelinstan. Anda mungkin harus berpikir lebihdalam lagiuntuk meyakinkan diri Anda sendiri bahwateknikyangsayagunakanuntukmengubahsatubasiskedalambasislainnya adalahbenar.JikaAndasudahyakin,makakitadapatmenggunakanmetodeberikut untukmenulisulangmetodeaddTime: publicstaticTimeaddTime(Timet1,Timet2){ doubleseconds=convertToSeconds(t1)+ convertToSeconds(t2); returnnewTime(seconds); 205
9.13 Generalisasi
Dalambeberapakasus,mengubahsatubentukdaribasis60kebasis10atausebaliknya adalahlebihsulitdaripadaberpacudenganwaktuitusendiri.Konversisuatubasisitu lebihabstrak;bahkanintuisikitaterhadapberpacudenganwaktuitusendirilebih baik. Namun jika kita mempunyai pemahaman mendalam untuk memperlakukan waktu sebagai angka berbasis 60, lalu membuat investasi dengan cara menulis metode pengubah/konverter (convertToSecond dan konstruktor ketiga), maka kita akan mendapatkanprogramyanglebihpendek,lebihenakuntukdibacadandidebug,juga lebihandal. Kitajugaakanlebihmudahuntukmenambahkanbeberapafiturdikesempatanlainnya. Misalnya,AndamembayangkanuntukmengurangiduaTimelalumencaridurasi/tempo antara keduanya. Pendekatan yang naif adalah dengan mengimplementasikan suatu pengurangan yang lengkap dengan teknik peminjaman. Menggunakan metode pengubahakanlebihmudah. Ironisnya, terkadang tidak menganggap ringan suatu masalah justru akan membuat masalah itu menjadi 'ringan' dengan sendirinya. (semakin kecil kasuskasus khusus, makaakansemakinkecilpulakesempatanuntukmembuaterror)
206
9.14 Algoritma
Ketika Anda menulissebuahsolusiumum untuksuatumasalah,sebagai lawan dari solusispesifikuntuksuatumasalahkhusus,sebenarnyaAndasudahmenulisapayang disebut dengan algoritma. Saya menyebut kata ini dalam bab 1, tapi tidak mendefinisikannyasecaramendalam.Tidaklahmudahuntukmendefinisikannya,jadi sayaakanmencobabeberapapendekatan. Pertama, pikirkanlah beberapa hal yang tidak termasuk algoritma. Sebagai contoh, ketika Anda telah belajar untuk mengalikan beberapa angka berdigit tunggal, Anda mungkiningatakantabelperkalian.Sebagaidampaknya,Andamengingat100solusi khusus,jadipengetahuanAndatersebutbelumlahtermasukkedalamapayangdisebut denganalgoritma. TapijikaAndaadalahseorangpemalas,Andamungkinakanmencuranginyadengan mengambil beberapa trik di dalamnya. Sebagai contoh, untuk menemukan hasil perkalianndengan9,Andadapatmenulisn1sebagaidigitpertama dan10n sebagaidigitkedua.Trikinimerupakansolusiumumuntukmengalikansebuaangka berdigittunggaldengan9.Nah,inibarualgoritma! Dengan cara yang sama, teknikteknik yang sudah Anda pelajari ketika melakukan penjumlahandenganpenyimpanan,pengurangandenganpeminjaman,danpembagian yangpanjangjugatermasukalgoritma.Salahsatusifatalgoritmaadalahbahwaiasama sekalitidakmembutuhkankecerdasandidalamnya. Ia merupakan proses mekanik dimanasetiapproses,dariawalhinggaakhir,dibuatberdasarkansekumpulanaturan tertentu. Menurutpendapatsaya,adalahmemalukanbagiseorangmanusiauntukmenghabiskan begitu banyak waktu di sekolah hanya untuk mengeksekusi algoritma yang, secara harfiah,tidakmelibatkankecerdasansamasekali. 207
Justru, proses ketika merancang algoritma itu sendirilah yang menarik, menantang intelektual,sekaligussebagaipusatdariapayangkitasebutdenganprogramming. Beberapahalyangdilakukanolehmanusiasecaraalamiah,tanpakesulitanataupun kesadaranpikiran,adalahhalyangpalingsulituntukditerjemahkandenganalgoritma. Memahamibahasanaturaladalahsalahsatucontohyangbagus.Kitasemuamemang melakukannya, tapi sampai sejauh ini, belum ada satu orang pun yang mampu menjelaskanbagaimanacarakitamelakukannya,setidaknyadalambentukalgoritma. Nantinya,Andaakanberkesempatanuntukmeracangsuatualgoritmasederhanauntuk beberapamasalah.
9.15 DaftarKataKata
Istilah Arti Sebelumya,sayatelahmendefinisikankelassebagaisebuah koleksi/kumpulandarimetodemetodeyangsalingberkaitan. Class(kelas) Dalambabinikitamempelajaribahwasebuahdefinisiuntuk kelasjugamerupakansebuahtemplateuntuktipebarusuatu objek. Instance(instan) Constructor (konstruktor) Project(proyek) Startupclass Salahsatuanggotakelas.Setiapobjekmerupakaninstandari suatukelas. Metodekhususyangmenginisialisasivariabelvariabelinstan dariobjekyangbaruakandibuat. Sebuahkoleksidarisatuataulebihdefinisikelas(satukelas persatufile)yangmembentuksebuahprogram. Kelasyangmengandungmetodemain,tempatdimana
208
Istilah eksekusiprogramdimulai.
Arti Sebuahmetodeyanghasilnyabergantungkepadaparamater
Function(fungsi)
parameternyasendiri,dantidakmemberikandampakapapun selainnilaiyangdikembalikannya.
modifier
Fillinmethod
algoritma
Suatuhimpunanaturanyangdigunakanuntukmenyelesaikan suatumasalahdenganprosesmekanis.
9.16 Latihan
Latihan9.1 Dalam permainan Scrabble1, setiap petak mengandung sebuah huruf, yang bisa digunakanuntukmengejasebuahkata,lalusebuahnilai(score),yangdigunakanuntuk menentukannilaidarisetiapkata. a) BuatlahsebuahdefinisikelasdengannamaTileyangmerepresetasikanpetakpetak Scrabble.Variabelvariabelinsatannyaharuslahsebuahkarakterdengannamaletter dansebuahintegerdengannamavalue. b) Tulislahsebuahkonstruktoryangmenggunakanparameterparameterdengannama letterdanvaluelaluinisialisasilahvariabelvariabelinstannya. c) TulislahsebuahmetodedengannamaprintTileyangmenggunakansatuobjekTile 209
sebagaiparameterlalumencetakvariabelvariabelinstannyadalamformatyangenak danmudahuntukdibaca. d) TulislahsebuahmetodedengannamatestFileyangdapatmenghasilkansatuobjek TiledenganhurufZdannilai10,lalugunakanprintTileuntukmencetakkeadaan (thestate)objektersebut. IntidarilatihaniniadalahuntukmelatihAndamemahamisisisisimekanispembuatan definisikelasyangbarusekaligusmembuatkodeyangdigunakanuntukmengujinya. Latihan9.2 TulislahsebuahdefinisikelasuntukDate,sebuahtipeobjekyangberisitigainteger, yakniyear,month,danday.Kelasiniharusmenyediakanduakonstruktor.Konstruktor Pertama tidak boleh menggunakan parameter apapun. Sedangkan konstruktor kedua harusmenggunakanyear,month,dandaysebagaiparameter,kemudianmenggunakan ketiganyauntukmenginisialisasivariabelvariabelinstan. TambahkankodekedalammainyangmembuatsebuahobjekDatebarudengannama birthday. Objek yang baru tersebut harus berisi tanggal lahir Anda. Anda dapat menggunakankeduakonstruktortersebut. Latihan9.3 Sebuah bilangan rasional (rational number) adalah suatu bilangan yang dapat ditampilkansebagaisuaturasio(perbadingan)dariduainteger.Contohnya;2/3adalah bilanganrasional,danAndapundapatmenganggap7sebagaibilanganrasionaldengan implisit 1 dalam denominatornya. Untuk tugas kali ini, Ada akan menulis sebuah definisikelasuntukbilanganrasional. a) Perhatikan kode berikut ini dan pastikan Anda dapat memahami apa yang dikerjakannya: publicclassComplex { 210
doublereal,imag; //simpleconstructor publicComplex(){ this.real=0.0;this.imag=0.0; } //constructorthattakesarguments publicComplex(doublereal,doubleimag){ this.real=real;this.imag=imag; } publicstaticvoidprintComplex(Complexc){ System.out.println (c.real + " + " + c.imag + "i"); } //conjugateisamodifier publicstaticvoidconjugate(Complexc){ c.imag=c.imag; } //absisafunctionthatreturnsaprimitive publicstaticdoubleabs(Complexc){ returnMath.sqrt(c.real*c.real+c.imag*c.imag); } //addisafunctionthatreturnsanewComplexobject publicstaticComplexadd(Complexa,Complexb){ returnnewComplex(a.real+b.real,a.imag+b.imag); } publicstaticvoidmain(Stringargs[]){ //usethefirstconstructor Complexx=newComplex(); 211
x.real=1.0; x.imag=2.0; //usethesecondconstructor Complexy=newComplex(3.0,4.0); System.out.println(Complex.abs(y)); Complex.conjugate(x); Complex.printComplex(x); Complex.printComplex(y); Complexs=Complex.add(x,y); Complex.printComplex(s); } } b) Buatlah sebuah program dengan nama Rational.java yang mendefinisikan sebuah kelas dengan nama Rational. Suatu objek Rational haruslah memiliki 2 variabel instan berupa integer yang digunakan untuk menyimpan nilai numerator dan denumeratordaribilanganrasional. c) Tulislahsebuahkonstruktortanpaparameteryangmenginisialisasikeduavariabel instantersebutdengannilai0. d) Tulislah sebuah metode dengan nama printRational yang menggunakan objek Rational sebagai sebuah argumen lalu mencetaknya ke dalam format yang dapat diterimaolehAndasendiri. e) Tulislahsebuahmetodemainyangmampumenghasilkansebuahobjekbarubertipe Rational,inisialisasilahvariabelvariabelinstannyadengannilainilaitertentu,lalu cetaklahobjektersebut. f) Sampai sejauh ini, Anda telah membuat programprogram yang dapat diuji (debuggable),meskidalamjumlahyangtidakterlalubanyak.Sekarangujilahsemua 212
programitu,laludebuglahjikamemangperlu. g) TulislahsebuahkonstruktorkeduauntukkelasAnda.Kelasinimenggunakandua argumenyangsekaligusberfungsiuntukmenginisialisasivariabelvariabelinstan. h) Tulislah sebuah metode dengan nama negate yang mengubah tanda dari suatu bilanganrasional.Metodeiniharuslahtermasukkedalamtipemodifieryangakan mengembalikanvoid.Tambahkanbarisbariskedalammetodemainuntukmenguji metodebaruitu. i) Tulislah sebuah metode dengan nama invert yang membalik angka dengan cara menukar(swapping)numeratordengandenumerator.Ingatingatlahpola swapping yangtelahkitalihatsebelumnya.Ujilahmetodeinidenganmenambahkanbeberapa bariskodedalammetodemain. j) Tulislah sebuah metode dengan nama toDouble yang dapat mengubah bilangan rasional ke bentuk double (bilangan floatingpoint) sekaligus mengembalikan hasilnya.Metodeinitermasukkedalamkelompokfungsimurni;jadiiatidakakan mengubah atau memodifikasi objek yang dioperasikannya. Lalu seperti biasanya, ujilahmetodeyangbaruAndabuatitu. k) Tulislah sebuah modifier dengan nama reduce yang dapat mengurangi sebuah bilanganrasionalsampaikebentuknya(term)yangterkecildengancaramenemukan GCD darinumeratordandenumeratoruntukkemudianmembagiatasdanbawah dengan GCD. Metode ini seharusnya berupa fungsi murni yang tidak mengubah variabelvariabelinstanmilikobjektempatdimanadiadipanggil. l) Tulislahsebuahmetodedengannamaaddyangmenggunakanduabilanganrational sebagaiargumendanmengembalikansebuahobjekRationalyangbaru.Objekyang dikembalikan,jelas,harusmengandungjumlahdarikeduaargumentersebut. Tujuan dari latihan ini adalah untuk menulis sebuah definisi kelas yang melibatkan berbagaijenismetodesekaligusyakni;konstruktor,modifier,danfungsifungsimurni. 213
214
Bab10 Array
Array adalah suatu kumpulan nilai yang diidentifikasi dengan sebuah indeks. Anda dapatmembuatsebuaharrayberisinilainilaiyangbertipeint,double,atautipelainnya. Tapiingat,semuanilaitersebutharussamatipenya. Dilihatdarisintaksnya,tipearraytampaksepertitipeJavalainnyakecualibahwatipe inidiikutidengansimbol'[]'.sebagaicontoh,int[]adalahtipearrayuntukintegerdan double[]adalahtipearrayuntukdouble. Andadapatmendeklarasikanvariabelvariabelbertipeinidengancarayangsudahlazim digunakan: int[]count; double[]values; SampaiAndamenginisialisasivariabelvariabelini,semuaakan diinisialisasi dengan null.Untukmembuatarray,gunakanperintahnew. count=newint[4]; values=newdouble[size]; Assignmentpertamamembuatvariabelcountakanmengacupadasebuaharrayyang berisiempatnilaibertipeinteger.SementaraAssignmentkeduaakan menyebabkan valuesmengacupadasuatuarraybertipedouble.Jumlahelemendalamvariabelvalues bergantung kepada size. Anda dapat menggunakan ekspresi integer apapun untuk membuatukuranarray. Gambarberikutinimenunjukkanrepresentasiarraydalamdiagramkeadaan.
215
Nomoryangdicetaktebaldidalamkotakmerupakanelemendariarray.Sedangkan nomornomor yang berada di luar kotak merupakan indeks yang digunakan untuk mengidentifikasisetiapkotak.KetikaAndamengalokasikansebuaharraybaru,elemen elemennyaakandiinisialisasikenol(0).
10.1 MengaksesElemen
Untukmenyimpannilainilaididalamarray,gunakanlahoperator[].Sebagaicontoh, count[0]akanmengacukepadaelemenke0dariarraytersebut.Sedangkancount[1] akanmengacukepadaelemenke1arraytersebut. Andadapatmenggunakanoperator[]dimanapundidalamsebuahekspresi: count[0]=7; count[1]=count[0]*2; count[2]++; count[3]=60; SemuapernyataandiatasmerupakanbentukassignmentyanglegaldalamJava.Berikut iniadalahpengaruhyangditimbulkanolehlampirankodediatas:
Mulai sekarangAnda harusmemperhatikan bahwakeempat elemendalamarrayini diindeksmulaidari0sampai dengan3.Iniberartibahwatidakadaelemendengan nomorindeksyangsamadengan4.Andasemestinyasudahterbiasadenganbentuk bentuksepertiinikarenasebelumnyakitasudahmelihathalyangsamaterjadipada penomoranindeksuntukvariabelbertipedataString.Meskipunbegitu,terkadangkita seringkalimelakukankesalahandenganmenggunakannomorindeksyangdiluarbatas array itu sendiri. Kesalahan semacam ini akan menghasilkan sebuah eksepsi, yakni ArrayOutOfBoundsExceptions.Laiknya yangterjadipadakemuculansemuaeksepsi, 216
Andajugaakanmendapatkansebuahpesanerroryangakanmenyebabkanterhentinya eksekusiprogramAnda. Andadapatmenggunakanekspresiapapunsebagaisuatuindeks,selamaiabertipedata int.Salahsatucarayangpalingumumuntukmengindekssebuaharrayadalahdengan menggunakanvariabelperulangan(loopvariable).Simaklahcontohberikutini: inti=0; while(i<4){ System.out.println(count[i]); i++; } Bentuk ini merupakan bentuk perulangan while yang lazim digunakan untuk menghitungindeksmulaidariindeks0hingga4.ketikavariabelperulangan,i,berisi nilai 4, syarat perulangan tersebut akan menghasilkan kesalahan. Kesalahan ini menyebabkanterhentinya eksekusiprogram.Olehkarenaitu,badandariperulangan tersebuthanyadieksekusiketikaisamadengan0,1,2dan3. Setiapkalikitamelewatiperulangandiatas,kitamenggunakanvariabelisebagaiindeks untukarray.Bentukpenelusuranarraysepertiinimerupakanbentukyangpalingsering digunakan.Arraydanperulanganmemadubersamalaksanamemakansatemadurayang gurihdenganwedangjahemanisnanhangat.
10.2 MenyalinArray
KetikaAndamenyalinsebuahvariabelbertipearray,ingatlahbahwaAndasebenarnya sedangmenyalinsebuahacuankepadaarraytersebut.Sebagaicontoh: double[]a=newdouble[3]; double[]b=a;
217
Perubahan apapun yang Anda lakukan pada satu array akan memberikan pengaruh kepadaarraylainnya.MungkininibukanlahperilakuyangAndainginkan;sebaliknya, Andaharusmembuatsebuahsalinandariarray,denganmengalokasikansebuaharray barudanmenyalinsetiapelemendariastuarraykearraylainnya. double[]b=newdouble[3]; inti=0; while(i<4){ b[i]=a[i]; i++; }
10.3 BentukPerulanganfor
Perulanganperulangan yang sudah kita tulis sejauh ini merupakan perulangan yang sudah terlalu sering kita lihat. Semuanya dimulai dengan menginisialisasi sebuah variabel;menggunakansuatutest,atausebuahpersyaratan,yangbergantungkepada variabelitusendiri;laludidalamperulanganitumerekamengerjakansesuatuuntuk variabeltersebut,sepertimisalnyamelakukanincrementuntuknya. Adasebuahbentukperulanganalternatifbagibentuksangatumumsepertidiatas,yakni perulanganfor.Bentukinimampumengekspresikanperulangansecaratepatdanlugas. Bentukumumsintaksnyatampaksebagaiberikut: for(INITIALIZER;CONDITION;INCREMENTOR){ BODY 218
} Pernyataaninieqivalendengan INITIALIZER; while(CONDITION){ BODY INCREMENTOR } Selainlebihlugas,bentukinijugalebihmudahuntukdibaca.Inidisebabkankarena semuapernyataanyagterkaitdenganperulanganitusendiriditempatkandidalamsatu baris.Sebagaicontoh: for(inti=0;i<4;i++){ System.out.println(count[i]); } Eqivalendengan inti=0; while(i<4){ System.out.println(count[i]); i++; } Untuk latihan Anda, tulislah sebuah perulangan for yang mampu menyalin elemen elemenyangterdapatdalamsebuaharray.
219
10.4 ArraydanObjek
Dalambeberapakesempatan,arraybertingkahlakulaiknyaobjek:
ketikaAndamendeklarasikansebuahvariabelarray,Andaakanmendapatkan sebuahacuan/referensikesebuaharray.
Andaharusmenggunakanperintahnewuntukmembuatsebuaharray. Ketika Anda melewatkan sebuah array sebagai argumen, Anda berarti melewatkansebuahacuan,yangberartibahwametodeyangAndapanggildapat mengubahelemenyangdikandungarray.
Beberapa objek yang sudah kita lihat, seperti Rectangles, dapat disamakan dengan array,dalamartianbahwakeduanyamerupakankumpulandarinilainilaiyangdiberi nama. Hal ini mengundang sebuah pertanyaan, Apa beda array dengan 4 elemen bertipeintegerdengansebuahobjekbertipeRectangle?; JikaAndamelihatkembalidefinisiarraydiawalbab,Andaakanmenemukansebuah perbedaan,yaknibahwaelemendarisebuaharraydiidentifikasimenggunakanindeks, sementaraelemenelemen(variabelinstan)darisuatuobjekmenggunakannama,seperti x,width,dst. Perbedaanlainantaraarraydanobjekadalahbahwasemuaelemendarisebuaharray haruslah bertipe sama. Meskipun hal yang sama juga terjadi pada objek Rectangle, namun pada kesempatan lain kita juga mengetahui bahwa ada objek lain yang mempunyaivariabelvariabelinstandengantipedatayangberbedabeda.Cobalihat kembaliobjekTime.
10.5 PanjangArray
Sebenarnya,arraysudahmemilikisatuvariabelinstan,yaknilength.Mudahditerka, variabel ini berisi informasi (nilai) mengenai panjang suatu array (jumlah elemen 220
Eksekusiterakhiryangterjadidalambadanperulangandiatasadalahketika i sama dengan a.length 1. ekspresi ini merupakan indeks untuk elemen terakhir array tersebut.Ketikaisamadengana.length,syaratperulanganakanbernilaisalahsehingga badanperulangantidakakandieksekusilagi.Halinimenguntungkanuntukkitakarena jika ekspresi tersebut sampai dieksekusi maka eksepsi tidak akan dapat dihindari. Lampiran kode ini mengasumsikan bahwa array b mempunyai jumlah elemen yang samadenganarraya. Sebagailatihan,tulislahsebuahmetodecloneArrayyangmenggunakansebuaharray bertipe integer sebagai parameter. Metode ini nantinya akan mampu menghasilkan sebuah array baru yang memiliki ukuran yang sama, menyalin elemenelemen dari arraypertamakearrayyangbaru,lalumengembalikannilaikembalianyangberupa acuankearraybarutersebut.
10.6 AngkaAngkaAcak(Random)
Programprogramkomputerpadaumumnyaselalumengerjakanhalyangsamasetiap kalimerekadieksekusi.Sifatsepertiinimembuatprogramprogramkomputerpantas disebutsebagaisesuatuyangdeterministik.Biasanya,sesuatuyangdeterminisadalah 221
halyangbaikkarenakitacenderunguntukmengharapkanperhitunganyangsamauntuk menghasilkanhasilyangsamapula.Namununtukbeberapaaplikasi,ternyatakitalebih menginginkansebuahkomputeryangmemilikisifattidakbisaditerka(unpredictable). Permainanpermainan(games)yangdimainkandengansebuahkomputeradalahcontoh yangjelas,tapimasihbanyaklagicontohyanglaintentunya. Membuatsebuahprogramyangbenarbenarbersifatnondeterministikadalahperkara yangsangattidakmudah.Namuntetapadacarauntukmembuatsebuahprogramagar tampakbersifatnondeterministik.Salahsatucaraadalahdenganmenggunakanangka angkaacaklalumemanfaatkannyauntukmenentukankeluaran/hasilsebuahprogram. Javamenyediakanmetodebawaanyangdapatmembuatangkaangka pseudorandom (imitasiterhadapdefinisiangkarandomsesungguhnya).Angkaangkainisebenarnya tidaklahsungguhsungguhrandomsecaramatematis,tapiuntuktujuanyanghendakkita capai,merekatampaknyabisamengerjakanapayangkitamaksudkan. Periksalah dokumentasi untuk metode random dalam kelas Math. Nilai kembalian merupakanangkabertipedoubleantara0.0dan1.0.untuklebihjelasnya;angkaangka inilebihbesaratausamadengan0.0dankurangdari1.0.SetiapkaliAndamemanggil metoderandom,Andaakanmedapatkanangkaberikutnyadalamurutanyangbersifat pseudorandom(aliastidakterurut).Untukmelihatcontohnya,eksekusilahperulangan ini: for(inti=0;i<10;i++){ doublex=Math.random(); System.out.println(x); } Untukmenghasilkanbilanganacakbertipedoubleantara0.0denganbatasatasyang berupavariabelsepertihigh,Andadapatmengalikan xdenganhigh.
222
Bagaimana cara Anda membuat sebuah bilangan acak antara variabel low dengan high?BagaimanacaraAndamembuatbilanganacakbertipeinteger? Latihan10.1 TulislahsebuahmetoderandomDoubleyangmenggunakanduavariabelbertipedouble, yaknilowdanhigh,yangmampumengembalikannilaiacakbertipedouble,yaknix dimanalowx<high. Latihan10.2 TulislahsebuahmetoderandomIntyangmenggunakanduaargumen,yaknilowdan high, yangmampumengembalikan nilaiacak bertipeintegerdiantara lowdanhigh dimanalowxhigh.
10.7 ArraydariAngkaangkaRandom(Acak)
JikaimplementasimetoderandomIntbuatanAndaberhasil,makasetiapnilaidalam interval (range) antara low dan high harus memiliki probabilitas kemunculan yang sama.JikaAndamembuatsebuahderetanangkayangpanjang,makasetiapnilaiharus muncul,setidaknyamendekati,angkayangsamasetiapkalikemunculannya. SalahsatucarauntukmengujimetodeAndaadalahdenganmembuatangkaangkaacak dalam jumlah yang banyak, lalu menyimpannya ke dalam array, untuk kemudian menghitungjumlahkemunculansetiapnilaiyangtelahditampilkan. Metode berikut ini menggunakan satu argumen, yakni ukuran array. Metode ini mengalokasikan sebuah array baru yang berisi elemenelemen bertipe integer. Kemudian mengisinya dengan bilanganbilangan acak, lalu mengembalikan sebuah acuan/referensikepadaarrayyangbaru. publicstaticint[]randomArray(intn){
223
2 44 81
Hasilinikelihatansepertisungguhsungguhacak.HasilyangAndaperolehmungkin akanberbeda. Jika ini merupakan hasil ujian, maka ini adalah hasil ujian yang buruk, sang guru mungkinakanmenampilkanhasilnyakepadakelasdalambentukhistogram.Histogram merupakan suatu kumpulan penghitungpenghitung (counter) yang menyimpan jejak mengenaijumlahkemunculansuatunilaidalamsetiapkesempatan. Untuknilainilaiujian,kitamungkinmenyediakan10penghitunguntukmenyimpan jejak mengenai berapa banyak murid yang mendapatkan nilai dalam interval 90an, 80an, dst. Subbab berikutnya akan memperlihatkan Anda mengenai cara untuk membuatsuatuhistogram.
10.8 Pencacahan
Sebuahpendekatanyangbagusuntukmasalahmasalahsepertiiniadalahdengancara memikirkansebuahmetodesederhanayangmudahuntukditulis,sekaligusmemiliki kemungkinanuntukdimanfaatkan.KemudianAndadapatmengkombinasikannyauntuk menghasilkansebuahsolusi.Tentu,adalahtidakmudahuntukmengetahuimetodemana yang bisa dimanfaatkan dalam waktu yang singkat, tapi seiring meningkatnya pengalamanAnda,makaakansemakinbanyakpulaideideAnda. Selainitu,terkadangkitajugatidakbisaselalumenyadaridenganjelasdanpastisuatu halyangmenurutkitamudahuntukditulis.Namunpendekatanyangmungkinberhasil adalahdengancaramencaripenyelesaianatassubmasalahyangsesuaidenganpolapola masalahyangsebelumnyasudahpernahAndalihat. 225
Kembali ke subbab 7.7, kita telah melihat sebuah perulangan yang melakukan penelusuransebuahstringlalumenghitungjumlahkemunculansuatuhuruf.Andadapat menganggap pola yang dianut oleh program ini sebagai sebuah pola dengan nama penelusurandanpenghitungan.Elemenelemendalampolainiantaralain:
Sebuah kumpulan kontainer yang dapat ditelusuri, seperti sebuah array atau string.
SebuahpengujianyangdapatAndalakukankepadasetiapelemenyangberada didalamkontainertersebut.
Sebuah pencacah (counter) yang menyimpan jejak tentang berapa banyak elemenyangtelahmelewatiujian.
Dalamkasusini,kontaineryangdimaksudkanadalahsuatuarrayyangbertipeinteger. Pengujian yang dilakukan adalah dengan cara memasukkan nilainilai yang ada ke dalamintervalintervalnilaiyangada. BerikutiniadalahmetodeinRangeyangmenghitungjumlahsuatuelemendalamarray yang masukke dalam interval nilai yangada. Parameterparameter yangdigunakan adalaharraydanduaintegeryangakanmenentukanbatasatasdanbawahsuatuinterval. public static int inRange (int[] a, int low, int high){ intcount=0; for(inti=0;i<a.length;i++){ if(a[i]>=low&&a[i]<high)count++; } returncount; } Ketikasayamendeskripsikanmetodeini,sayatidakterlalupeduliapakahsuatunilai yangsamadenganlowatauhighakanturutmasukkedalamintervalataukahtidak,tapi 226
dari kodetersebutAnda dapat melihatbahwa lowakanikut masuksementara high tidak.Darisinikitalangsungdapatmencegahterjadinya penghitungangandauntuk satuelemen. Sekarangkitadapatmenghitungbanyaknilai(cacahbukanjumlah)yangberadadalam intervalyangkitainginkan: int[]scores=randomArray(30); inta=inRange(scores,90,100); intb=inRange(scores,80,90); intc=inRange(scores,70,80); intd=inRange(scores,60,70); intf=inRange(scores,0,60);
10.9 Histogram
Kode yang kita tulis dan lihat sejauh ini tampaknya seperti sesuatu yang selalu berulangulang.Tetapiselamaintervalnilaiyangkitamilikitidaklahterlalubesar,hal inibukanlahmasalahserius.TapicobabayangkanjikaAndamemiliki100interval. ApakahAndamaumenuliskodeberikutini? intcount0=inRange(scores,0,1); intcount1=inRange(scores,1,2); intcount2=inRange(scores,2,3); ... intcount3=inRange(scores,99,100); Saya pikir tidak! Apa yang kita inginkan sesungguhnya adalah suatu cara untuk menyimpan100integer,danlebihbaguslagikalaukitabisamemakaisebuahindeks untukmengaksesnya.Biarsayatebak,Andapastilangsungterpikirdenganarray! 227
Pola penghitungan yang akan kita gunakan adalah sama, tak peduli apakah kita menggunakansatupencacah(singlecounter)atausatuarrayberisipencacah. Dalam kasusini,kitamenginisialisasiarraydiluarperulangan;lalu,didalamperulanganitu, kitapanggilmetodeinRangeuntukmenyimpanhasilnya: int[]counts=newint[100]; for(inti=0;i<100;i++){ counts[i]=inRange(scores,i,i+1); } Satusatunya'kecurangan'disiniadalahbahwakitamenggunakanvariabelperulangan untukduakepentingansekaligus:sebagaiindeksuntukarrayjugasebagaiparameter untukinRange.
10.10 SolusiSinglePass
Meskipun kode ini bekerja, tapi ia belum bisa dianggap efisien. Karena setiap kali memanggil inRange, kode ini akan menelusuri semua array. Ketika jumlah interval bertambah,makabertambahpulawaktuuntukpenelusuran. Akan lebih baik bagi kita untuk membuat satu singlepass yang dapat menelusuri seluruharray,danuntuksetiapnilaiyangditelusuri,cukupdenganmenghitunginterval tempatnilaitersebutberada.Kemudianbarulahkitadapatmenaikkannilaipencacah yangkitagunakan.Dalamcontohini,aspekkomputasimenjaditidakbegitupenting. Haliniterjadikarenakitadapatmenggunakannilaiitusendirisebagaiindeksuntuk arraypencacah(arrayofcounters). Berikutiniadalahkodeyangmampumenelusurisebuaharrayyangberisinilainilai (skor)denganhanyasatukalipenelusuran.Hasilnyaadalahsebuahhistogram.
228
Latihan10.3 EnkapsulasilahkodeinidalamsatumetodedengannamascoreHistyangmenggunakan arrayberisinilainilai(skor)lalumengembalikansebuahhistogramyangberisinilai nilaidalamarraytersebut. Modifikasilahmetodetersebutsehinggahistogramhanyamemiliki10pencacah, lalu menghitungbanyak nilaiyangmunculdalamsetiap intervalnya; maksudnya banyak nilaidalaminterval90an,80an,dst.
10.11 DaftarKataKata
Istilah Array Arti Kumpulannilainilaiyangdiberinama,dimanasemuanilai tersebut memiliki tipe yang sama dan setiap nilai diidentifikasidenganindeks. koleksi elemen index Suatubentukstrukturdatayangberisikumpulanitematau elemen Salahsatunilaididalamarray.Operator[]digunakanuntuk memilihelemendalamsuatuarray. Variabel integer atau nilai yang digunakan untuk mengindikasi(menunjukkan)satuelemendalamarray.
229
deterministik
pseudorandom
yangdiacak,tetapisebenarnyatidak.Angkaangkatersebut hanyalahhasildarikomputasiyangdeterminis. Array bertipe integer dimana setiap nilai integer akan
histogram
10.12 Latihan
Latihan10.4 Tulislah metode areFactors yang menggunakan sebuah integer, n, dan sebuah array bertipe integer, lalu mengembalikan true jika angkaangka dalam array merupakan faktordarin(dengankatalain;nbisadibagidengansemuaangkatersebut).Petunjuk: LihatLatihan5.1 Latihan10.5 Tulislahmetodeyangmenggunakansebuaharrayintegerdansebuahintegerdengan namatargetsebagaiargumen.Metodeiniakanmengembalikannilaiyangberupaindeks tempatdimanatargetpertamakalimunculdalamarraytersebut.Jikanilaiyangdicari tidakditemukanmakametodeakanmengembalikannilai1. Latihan10.6 TulislahmetodearrayHistdengansebuaharrayintegersebagaiargumen,yangdapat menghasilkansebuaharrayhistogramyangbaru.Histograminiharusberisi11elemen dengantampilansebagaiberikut:
elemen t0 numbe rof elem ent sin the array that are <= 0
230
1 numbe rof elem ent sin the array that are == 1 2 numbe rof elem ent sin the array that are == 2 ... 9 numbe rof elem ent sin the array that are == 9 10 numb er of elemen ts in the array that are >= 10
Latihan10.7 Beberapa programmer tidaksetujudenganaturanumumyangmenyebutkan bahwa variabel dan metode haruslah diberi nama yang mengandung makna. Sebaliknya, mereka justru beranggapan bahwa variabel atau metode seharusnya dinamai setelah namabuahbuahan. Untuksetiapmetodedibawahini,tulislahsatukalimatyangmendeskripsikansecara abstrak tugas/fungsi yang dikerjakannya. Lalu untuk setiap variabel, identifikasilah peranyangdiembannya. publicstaticintbanana(int[]a){ intgrape=0; inti=0; while(i<a.length){ grape=grape+a[i]; i++; } returngrape; } publicstaticintapple(int[]a,intp){ inti=0; intpear=0; while(i<a.length){ 231
if(a[i]==p)pear++; i++; } returnpear; } publicstaticintgrapefruit(int[]a,intp){ for(inti=0;i<a.length;i++){ if(a[i]==p)returni; } return1; } Tujuan latihan ini adalah untuk melatih kemampuan Anda dalam membaca kode sekaligusmengenalipolapolapenyelesaianyangtelahkitalihatsebelumnya. Latihan10.8 a) Apaoutputyangdihasilkandariprogramberikutini? b) Gambarlahdiagramstackyangmenunjukkankeadaandariprogramsesaatsebelum musdikembalikan. c) Deskripsikandalambeberapakatamengenaiapayangdilakukanolehmus. publicstaticint[]make(intn){ int[]a=newint[n]; for(inti=0;i<n;i++){ a[i]=i+1; } returna; } 232
publicstaticvoiddub(int[]jub){ for(inti=0;i<jub.length;i++){ jub[i]*=2; } } publicstaticintmus(int[]zoo){ intfus=0; for(inti=0;i<zoo.length;i++){ fus=fus+zoo[i]; } returnfus; } publicstaticvoidmain(String[]args){ int[]bob=make(5); dub(bob); System.out.println(mus(bob)); } Latihan10.9 Umumnya, polapola yang digunakan untuk penelusuran array yang telah kita lihat sebelumnyadapatditulissecararekursif.Sebenarnyahalinitidaklazimdilakukan,tapi inibisamenjadilatihanyangbagusbuatkita. a) TulislahmetodemaxInrangeyangmenggunakansebuaharrayintegerdansebuah intervalindeks(lowIndexdanhighIndex).Metodeiniakanmencarinilaimaksimum 233
dalamarray,elemenelemenyangdicariberadadiantaralowIndexdanhighIndex, termasukdikeduaujungnya. Metodeiniharuslahbersifatrekursif.Jikapanjangintervaladalah1,yaituketika lowIndex == highIndex, maka kita akan segera mengetahui bahwa satusatunya elemen yang berada dalam interval tersebut adalah nilai maksimumnya. Dengan demikian,inilahbasecaseyangakankitagunakan. Jika terdapat lebih dari satu elemen dalam suatu interval, kita dapat memecah arraynya menjadi dua bagian; tentukan nilai maksimum dalam setiap bagian arraynya, lalu temukan nilai maksimum diantara nilai maksimum yang sudah ditentukansebelumya. b) Metodemetode seperti maxInRange seringkali mengundang 'kejanggalan' ketika digunakan. Untuk menemukan elemen terbesar dalam sebuah array, kita harus menyediakansebuahintervalyangmenyertakansemuaelemendalamarray. doublemax=maxInRange(array,0,a.length1); Tulislah metode max yang menggunakan sebuah array sebagai parameter dan maxInRangeuntukmenemukandanmengembalikannilaiterbesar.Metodemetode seperti max terkadang disebut juga metode pembungkus (wrapper methods). Disebut demikian karena metodemetode tersebut meyediakan sebuah lapisan abstraksi(layerofabstraction)disekelilingsuatumetodeyangjanggal.Selainitu, metode ini juga menyediakan sebuah antarmuka untuk lingkungan di luarnya sehingga bisa lebih mudah untuk digunakan. Metode yang mengerjakan komputasinyasendiridikealdenganistilah helpermethod.Kitaakanmelihatpola inilagidisubbab14.9. c) Tulislahsebuahversirekursifdarimetodefindmenggunakanpolawrapperhelper. Metode find harus menggunakan sebuah array integer sekaligus sebuah integer tujuan/target. Metode ini harus mengembalikan indeks dari lokasi awal dimana 234
integertargetmunculdidalamarray.Jikatidak,metodeakanmenghasilkan1. Latihan10.10 Salahsatucarayangtidakefisienuntukmengurutkanelemenelemendalamsuauarray adalah dengan cara menemukan elemen terbesar lalu menukarnya dengan elemen pertama, kemudian menemukan elemen terbesar kedua lalau menukarnya dengan elemenkedua,dst. a) Tulislah metode indexOfMaxInRange yang menggunakan sebuah array integer sebagai argumen, yang mampu menemukan elemen terbesar dalam interval yang telahditentukan,lalumengembalikanhasilyangberupanilaiindeksnya.Andadapat memodifikasi versi rekursif dari maxInRange atau Anda dapat menulis versi perulangannnyadariawal. b) Tulislah metode swapElemet yang menggunakan sebuah array integer dan dua indeks,yangmampumenukarelemenelemenyangberadapadaindeksyangtelah ditentukan. c) TulislahmetodesortArrayyangmenggunakansebuaharrayintegerbesertametode indexOfMaxInRangedanswapElementuntukmengurutkanarraydariyangterbesar hinggayangterkecil. Latihan10.11 TulislahmetodeletterHistyangmenggunakansebuahStringsebagaiparameter yang mampumenghasilkanhistogramdarihurufhurufyangberadadidalamString.Elemen ke0darihistogramharusberisijumlahhurufayangberadadalamstring,baikhuruf kecilmaupunkapital,sementaraelemenke26harusberisijumlahhurufzyangberada dalamstring.SolusiAndainiharusmenerapkanpola satukalipenelusuran.Jangan lebih! Latihan10.12
235
Sebuah kata disebut doubloon jika setiap huruf yang muncul dalam kata tersebut muncultepatduakali.Sebagaicontoh,katakataberikutinimerupakandoubloonyang sayatemukandalamkamusmilikku. Abba, Anna, appall, appearer, arraigning, horseshoer, beriberi, appeases, boob,
bilabial,
Caucasus, coco, Dada, deed, Emmett, Hannah, Otto, intestines, Isis, mama, Mimi, murmur, noon, papa, peep, reappear, redder,sees,Toto,Shanghaiings TulislahmetodeisDoubloonyangmengembalikannilaitruejikakatayangdimasukkan merupakandoubloondanfalsejikasebaliknya. Latihan10.13 Dalampermainanscrabble,setiappemainmemilikikotakkotakyangberisihurufdi dalamnya.Tujuanpermainaniniadalahuntukmembuathurufhurufyangpadaawalnya tidakberaturanmenjaditeratursehinggadapatdigunakanuntuk mengejakatakata. Sistempenilaianyangdigunakansangatmembingungkan,tetapisebagaipanduandasar, katayanglebihpanjanglebihbanyaknilainyaketimbangkatayanglebihpendek. BayangkansaatiniadaseseorangyangmemberiAndasebuahkumpulankotakyang berupaString,sepertiqijibolaluAndajugadiberiStringlainuntukmengujicoba, sepertijib.TulislahmetodetestWordyangmenggunakanduaStringini.Metodeini mengembalikannilaitruejikakumpulankotakyangdiberikandapatdigunakanuntuk mengejakata.Andadiperkenankanuntukmemilikilebihdarisatukotakdenganhuruf yangsama,tapiAndahanyabolehmenggunakanmasingmasingkotaksebanyaksatu kalisaja.Janganlebih! Latihan10.14
236
Dalam permainan Scrabble yang sebenarnya, ada beberapa kotak kosong yang bisa digunakansebagaiwildcards;yaknisebuahkotakkosongyangdapatdigunakanuntuk merepresentasikanhurufapapun. Pikirkanlah sebuah algoritma untuk testWord yang berkenaan dengan konsep wild cards. Tapi ingat! Jangan sampai terlalu jauh berurusan dengan detil implementasi, misalnyamemikirkan cara untukmerepresentasikan wild cards. Bukan itu! Cobalah untuk mendeskripsikan algoritmanya saja, menggunakan bahasa yang Anda kuasai, denganpseudocode,atauJava.
237
11.2 ObjekCard
JikaAndatidakakrabdenganpermainankartuyangbiasadimainkanolehbanyakorang diseluruhdunia,makasekarangadalahwaktuyangtepatuntukmemulainya.Karena kalautidak,babiniakanmenjadisiasia.Ada52kartudalamsebuahtumpukankartu (deck). Masingmasing kartu tersebut akan masuk ke dalam satu di antara empat kelompok(suit)yangada.Empatkelompoktersebutantaralain;Sekop(Spade),Hati (Heart), Permata (Diamond), dan Wajik (Club). Selain masuk ke dalam empat
238
kelompok, setiap kartu juga akan memiliki nomor urutan/peringkat (rank) yang membedakannyadengankartukartulainyangmasihadadalamkelompokyangsama. Nomorurutan/peringkatiniantaralain;As(ace),2,3,4,5,6,7,8,9,10,Jack,Queen, King.Dalampermainankartu,kartuAsbisabernilailebihtinggiketimbangkartuKing ataumalahlebihrendahketimbangkartu2.Halinitergantungdenganjenispermainan kartuyangdimainkan. Jikakitahendakmendefinisikansebuahobjekuntukmerepresentasikan permainan kartu,makakitabisadenganmudahmenyebutkanvariabelinstanyangdiperlukan:rank dansuit.Tepatsekali!Tapisayangnya,menentukantipedataapayangakandigunakan untuk menyimpan kedua variabel ini justru yang agak sulit. Kemungkinan pertama adalahStringyangbisamenyimpansesuatusepertiSpadeuntuk suit danQueen untuk rank.Satumasalahyangmunculdenganimplementasisepertiiniadalahkita akanmenemukankesulitanketikaharusmembandingkankartuuntukmemeriksakartu manayangmemilikisuitataurankyanglebihtinggi. Alternatif penyelesaian masalah adalah dengan menggunakan tipe integer untuk menyandi(encode)rankdansuit.Denganmelakukanpenyandian,bukanberartisaya inginmengerjakanapayangmungkinlangsungterpikirdikepalabanyakorang,yakni enkripsi,ataumenyandikeduavariabelinidengankoderahasia.Apayangdimaksud dengan penyandian oleh seorang ilmuwan komputer adalah sesuatu yang seperti buatlah sebuah bentuk pemetaan antara deretan angkaangka dengan sesuatu yang inginsayatampilkan.Sebagaicontoh, Spades 3 Hearts 2 Diamonds 1 Clubs 0
239
Manfaat yang jelas bisa kita lihat dari pemetaan ini adalah bahwa variabel suit dipetakanketipeintegerdalamkeadaanterurut.Haliniakanmemberikankemudahan untuk kitaketikahendakmembandingkansuitdengancaramembandingkaninteger. Pemetaan untuk variabel rank tampak sangat jelas; setiap nomor urut kartu akan dipetakan sesuai dengan integer yang sama, begitu juga dengan kartukartu yang menggunakansimbolsimbol: Jack 11 Queen 12 King 13 Alasansayamenggunakannotasimatematikauntukpemetaaniniadalahkarenamereka semua bukanlah bagian dari program Java yang akan kita buat. Mereka hanyalah merupakanbagiandarirancanganprogram(programdesign)yangtidakakankitaikut seratakansecaraeksplisitdidalamkode.DefinisikelasuntuktipeCardakantampak sebagaiberikut: classCard { intsuit,rank; publicCard(){ this.suit=0;this.rank=0; } publicCard(intsuit,intrank){ this.suit=suit;this.rank=rank; } } Seperti biasa, saya menyediakan dua konstruktor di sini, satu yang menggunakan
240
sebuahparameteruntuksetiapvariabelinstan,dansatulagiyangtidakmenggunakan satuparameterpun. Untuk membuat sebuah objek yang dapat merepresentasikan rank (urutan) 3 milik wajik,kitabisamenggunakanperintahnewsebagaiberikut: CardthreeOfClubs=newCard(0,3); Argumenpertama,0,merepresentasikankelompokwajik.
11.3 MetodeprintCard
Ketika Anda membuat sebuah kelas baru, langkah pertama yang biasanya Anda kerjakan adalah mendeklarasikan variabel instan dan menulis konstruktor konstruktornya.Kemudiandiikutidenganmenulismetodestandaryangharusdimiliki olehsemuaobjek,termasuksatumetodeyangakanmencetakobjektersebut,lalusatu atauduametodeuntukmembandingkanobjekobjek.Sayaakanmemulainyadengan metodeprintCard. UntukmencetakobjekCardyangdapatdibacadenganmudaholehmanusia,kitaakan memetakan kodekode integer ke bentuk yang berupa katakata. Cara alami untuk melakukannya adalah dengan menggunakan sebuah array berisi String. Anda bisa membuat sebuah array berisi String dengan cara yang sama seperti ketika Anda membuatsebuaharrayyangberisitipedataprimitif: String[]suits=newString[4]; Kemudiankitaisielemenelemenarrayinidengannilainilaisebagaiberikut: suits[0]="Clubs"; suits[1]="Diamonds"; suits[2]="Hearts"; suits[3]="Spades"; Membuat sebuah array dan langsung menginisialisasinya merupakan operasi yang 241
sangat sering dilakukan. Saking seringnya, sampaisampai Java malah sudah menyediakansintakskhususuntukmelakukannya:
String[] "Spades"}; suits = {"Clubs", "Diamonds" , "Hearts",
Elemenelemen array merupakan sesuatu yang mengacu (references) ke String, ketimbangmenjadi String itusendiri.Haliniadalahfaktaumumyangberlakuuntuk semuaarrayyangberisiobjekobjek,sebagaimanayangakansayabahaslebihdetaildi bagianberikutnya.Sekarang,yangkitabutuhkanadalaharrayberisiStringlainyang digunakanuntukmengkodebalik(decode)peringkatperingkatdalamkartu:
String[] ranks = { "narf", "Ace", "2", "3", "4", "5", "6", "7", "8","9", "10", "Jack", "Queen", "King" };
Elemen narf digunakan sebagai penjagatempat (placekeeper) untuk elemen ke0 dariarrayyangtidakakanpernahdipakaidalampermainankartu.Indeksarrayyang bisadipakaihanyalah1s.d.13.Elemenyangtidakdigunakaninimemangtidakpenting tentunya.Sebenarnyakitabisasajamemulainyadariurutanke0,sepertibiasa,tapi akanlebihbaikbagikitauntukmengkode2dengan2,3dengan3,4dengan4,dst. Dengan arrayarray ini, kita bisa memilih String yang tepat dengan menggunakan variabelsuitdanranksebagaiindeks.DalammetodeprintCard,
publi cst atic voi dpr intC ard( Car dc) {
242
Strin g[] su its = { "C lubs ", "Di amon ds", "Hear ts", "Spad es"} ; Strin g[] rank s = { "n arf" , "A ce", "2" , "3 ", "4", "5", "6"," 7", "8" ,"9 "," 10", "Ja ck", "Qu een" ,"K ing" }; Syste m.ou t.pr intl n (ran ks[c .ran k] + " of " + suits [c.s uit] ); }
11.4 MetodesameCard
Katasamatermasuksalahsatukatadaribeberapakatadalambahasaalami(natural language) yang tampaknya baru akan jelas maksudnya ketika Anda memberinya denganmaksudmaksudtertentu. Sebagaicontoh,jikasayaberkataChrisdansayamempunyaimobilyangsama,maka di sini saya bermaksud menginformasikan bahwa mobil miliknya dan milik saya mempunyaimodeldantahunpembuatanyangsama.Jikasayaberkatabahwa bahwa Chrisdansayamempunyaiibuyangsama,disinisayabermaksudmengatakanbahwa ibunyadanibusayaadalahsatuibuyangsama.Jadi,idemengenaikesamaanbisa dimaknaiberbedabedatergantungdengankontekskalimatnya. Ketika Anda berbicara mengenai objek, Anda juga akan menemui ambiguitas yang sama. Sebagai contoh, jika dua kartu adalah kartu yang sama, apakah itu berarti 243
keduanya memiliki data yang sama (rank dan suit), ataukah keduanya hanya merupakanduaobjekCardyangsama? Untuk melihat apakah dua objek berbeda mengacu ke objek yang sama, kita bisa menggunakanoperator==.Sebagaicontoh:
Card card1 =new Card(1, 11); Card card2 =card1; if (card1 ==card2) { System.ou t.prin tln ("card1 and card2 are the same object."); }
Bentuk kesamaan seperti ini disebut shallow equality (tidak dalam) karena hanya membandingkanobjekyangdiacu,bukanisidariobjektersebut. Untukmembandingkanisiobjektersebut deepquality kitabisamenulissebuah metodedengannamasameCard. publicstaticbooleansameCard(Cardc1,Cardc2){ return (c1.suit == c2.suit && c1.rank == c2.rank); }
merepresentasikankartuyangsama: Cardcard1=newCard(1,11);
244
Cardcard2=newCard(1,11); if(sameCard(card1,card2)){ System.out.println same } Dalamkasusini, card1 dan card2 adalahduaobjekberbedayangberisidatayang sama. ("card1 and card2 are the card.");
11.5 MetodecompareCard
Untuktipedatatipedataprimitif,terdapatoperatoroperatorkondisionalyangdapat membandingkannilainilaisekaligusmenentukannilaimanayanglebihbesardaripada nilai lainnya. Operatoroperator ini (<, >, dll) tidak bisa digunakan untuk tipetipe
245
objek. Khusus untuk String, ada sebuah metode builtin yang dinamai compareTo. UntukCard,kitaharusmenulisnyasendiri.Metodeiniakankitasebutsebagaimetode compareCard. Berikutnya, kita akan menggunakan metode ini untuk mengurutkan tumpukankartu. Beberapahimpunan/kelompok(set) databeradadalamkeadaanyangmemangsudah terurut.Iniartinya,Andabisamembandingkanduaelemenapapundarikelompokdata tersebut untuk kemudian langsung mengatakan elemen mana yang lebih besar atau sebaliknya. Angkaangka yang termasuk ke dalam kelompok tipe data integer dan floatingpointbisaAndajadikancontohdalamhalini.Namunadajugakelompokdata yangtidakterurutsecaraalami(baca:tidakuntukdiurutkan).Maksudnya,tidakada cara untuk menyebutkan bahwa satu elemen lebih besar daripada elemen lainnya. Sebagaicontoh,buahbuahanmerupakankelompokdatayangtidakbisaataumemang tidak untuk diurutkan. Hal inilah yang menyebabkan kita tidak akan pernah bisa membandingkan buah jeruk dengan buah apel menggunakan sudut pandang perbandingan antara dua angka seperti pada contoh sebelumnya. Dalam Java, tipe booleanjugatidaktermasukkedalamkelompoktipedataterurut.Olehkarenaitulah, kitatidakbisamenyebutTruelebihbesardaripadaFalse. Kelompok kartu yang biasa dimainkan bisa dianggap sebagai kelompok data yang terurutsecaraparsial.Maksudnya,terkadangkitamemangbisamembandingkandua kartu tetapi terkadang malah sebaliknya. Contohnya, saya mengetahui bahwa kartu wajikdengannomor3lebihtinggidaripadakartuwajikdengannomor2,dankartu permatabernomor3lebihtinggidaripadakartuwajikbernomorsama.Tapikartumana yang lebih baik, kartu wajik dengan nomor 3 ataukah kartu permata yang hanya bernomor2?Kartupertamamemilikiperingkatyanglebihtinggi,tapikartulainnya memilikikelompokyanglebihtinggi.
246
Agar kartukartu inibisadibandingkan,kitaharusmemutuskanvariabelmanayang lebihpenting,variabelrank(peringkat)ataukahsuit(kelompok).Jujursaja,duapilihan diatasakansangattergantungdenganseleramasingmasingindividu.Namununtuk kasus ini, saya berpendapat bahwa variabel suit lebih penting, karena ketika Anda membeli satusetkartu, kartukartu itutersusundalam susunan di manakartukartu wajikditempatkandiataspermatadankelompoklainnya.Bukandisusunberdasarkan nomorkartu. Dengan keputusan di atas, kita bisa menulis metode compareCard. Di sini kita membutuhkanduabuahCardsebagaiparameter,angka1sebagainilaikembalianjika kartuyangditulispertamamenangdan1jikasebaliknya,serta0jikakeduanyasama (darisegiisi/kandunganobjek Card tersebut).Terkadangakanmembingungkanjuga jikakitaselalumenggunakanketiganilaidiatassebagainilaikembalian,tetapifakta berkata lain, ketiga nilai tersebut sebenarnya telah menjadi standar untuk metode metodeyangberhubungandenganperbandingan. Awalnya,kitaakanmembandingkankartukartutersebutberdasarkankelompok: if(c1.suit>c2.suit)return1; if(c1.suit<c2.suit)return1;
akandianggaplebihrendahdaripadakartudengannomor2. Untuk latihan, perbaikilah metode di atas agar kartu As bisa bernilai lebih tinggi ketimbangkartuKing,laluenkapsulasilahkodeAndainikedalamsebuahmetode.
11.6 ArrayberisiCard
AlasansayamemilihCardsebagaiobjekuntukbabiniadalahkarenaterdapatsebuah manfaatjelasyangbisadidapatdariarrayberisikartu,yaknisebuahtumpukan.Berikut iniadalahlampirankodeuntukmembuatsebuahtumpukanyangberisi52kartu. Card[]deck=newCard[52]; Berikutiniadalahdiagramkeadaanuntukobjekini:
Halpentingyangharusdilihatdisiniadalahbahwaarrayyangkitabuathanyaberisi referensikeobjek;tapitidakmenampungobjekobjekCarditusendiri.Nilainilaidari elemen array diinisialisasi dengan null. Anda bisa mengakses elemenelemen array dengancarayangsudahlazimdipakai: if(deck[3]==null){ System.out.println("Nocardsyet!"); } TapijikaAndamencobamengaksesvariabelvariabelinstandariCardyangmemang tidak ada atau belum dideklarasikan, maka Anda akan mendapatkan NullPointerException. deck[2].rank;//NullPointerException Tidak perlu diperdebatkan lagi, sintaks di atas merupakan sintaks yang tepat untuk mengakses kartu dengan nomor 2 yang berada dalam tumpukan (sebenarnya yang
248
ketigakitamemulainyadariurutanke0bukan?).Iniadalahcontohlaindaribentuk composition, kombinasi antara sintaks untuk mengakses satu elemen dalam sebuah arraydansebuahvariabelinstandarisuatuobjek. CaratermudahuntukmengisisuatutumpukandenganobjekobjekCardadalahdengan menggunakanperulangantersarang(nestedloop): intindex=0; for(intsuit=0;suit<=3;suit++){ for(intrank=1;rank<=13;rank++){ deck[index]=newCard(suit,rank); index++; } } Perulanganbagianluarakanmenghasilkankelompokkelompokkartu,mulaidarinol sampaidengantiga(0s.d.3).Untuksetiapkelompokkartu,perulanganbagiandalam akanmenghasilkanperingkatnya,yaknimulaidari1s.d.13.Karenaperulangan(loop) bagianluardieksekusi4kalidanperulanganbagiandalam13kali,totaleksekusiyang terjadididalambadanperulanganadalah52kali(samadengan13x4). Sayamenggunakanvariabelindexuntukmelacakkeberadaankartuberikutnyadidalam tumpukan.Diagramkeadaanberikutinimenunjukkankeadaantumpukansetelahdua kartudimasukkan:
249
Latihan11.1 Enkapsulasilah kode pembuat tumpukan ini ke dalam sebuah metode dengan nama buildDeck yangtidakmenggunakanparameterdanmenghasilkansebuaharrayberisi kumpulanCard.
11.7 MetodeprintDeck
KetikaAndabekerjadenganarray,adalahsesuatuyangwajaruntukmenulissebuah metode yang akan mencetak isi array tersebut. Sebelumnya kita telah melihat pola penelusuran array beberapa kali. Jadi, Anda seharusnya sudah cukup akrab dengan metodeberikutini: publicstaticvoidprintDeck(Card[]deck){ for(inti=0;i<deck.length;i++){ printCard(deck[i]); } } Karenaparameter deck bertipe Card[],elemendalam deck akanbertipe Card.Oleh karenaitu,deck[i]merupakanargumenlegaluntukmetodeprintCard. 250
11.8 Searching
MetodeberikutnyayanginginsayatulisadalahfindCard.Metodeiniakanmelakukan pencariandidalamarrayberisiCarduntukmelihatapakaharraytersebutmemilikikartu yangsedangdicari.Mungkinmetodeinitidakjelasakandimanfaatkanuntukapa,tapi halinijustrumemberikankesempatanbagisayauntukmendemonstrasikanduacara untukmelakukanpencarian,yaitulinearsearchdanbisectionsearch. Teknik linearsearch lebihseringdigunakan;teknikinimenggabungkanpenelusuran tumpukan dan pembandingan setiap kartu dengan kartu yang kita cari. Ketika kita menemukannya,kitaakanmengembalikanindekslokasikartutersebut.Tapijikakita tidakmenemukannyadidalamtumpukan,kitamengembalikannilai1. public static int findCard (Card[] deck, Card card) { for(inti=0;i<deck.length;i++){ if(sameCard(deck[i],card))returni; } return1; } Argumenargumen findCard kitanamaidengannama card dan deck.Mungkinakan terlihatganjiljikakitamenggunakansebuahvariabeldengannamayangsamadengan tipenya (variabel card bertipe Card). Halsepertiiniadalahsesuatuyanglegaldan lazimdipakai,meskipunterkadanghalinijustruakanmembuatkodeyangkitatulis menjadi lebih sulit untuk dibaca. Namun dalam kasus ini, saya kira hal ini bisa berfungsidenganbaik. Metode ini akan langsung mengembalikan nilai kembalian ketika kartu yang dicari sudahditemukan.Iniberarti,kitatidakperlumenelusurisemuaindeksdalamtumpukan jika kartu yang dicari sudah ditemukan. Jika perulangan yang dilakukan sudah 251
dihentikan tanpa menemukan kartu yang dicari, kita akan segera tahu bahwa kartu tersebut tidak berada di dalam tumpukan. Oleh karena itu, metode ini akan mengembalikannilai1. Jikakartukartuyangberadadalamtumpukantidakberadadalamposisiyangterurut, makatidakadacarayanglebihcepatuntukmelakukanpencarianketimbangcaraini. Kitaharusmemeriksasetiapkartukarenatanpaini,kitatidakakanbisamemastikan bahwakartuyangkitacarimemangbenarbenartidakadadidalamtumpukanitu. NamunketikaAndamencarisebuahkatadidalamkamus,Andatidakmencarikata tersebut secara linear atau kata demi kata. Hal ini terjadi karena katakata tersebut berada dalam posisi yang sudah terurut secara alfabetis. Akibatnya, Anda mungkin menggunakansebuahalgoritmayangsamadenganbisectionsearch: 1. Mulailahmencaridaribagiantengah. 2. Pilihlah sebuah kata dalam halaman lalu bandingkanlah setiap kata tersebut dengankatayangAndacari. 3. JikaAndamenemukankatayangAndacari,berhenti. 4. JikakatayangsedangAndacari,secaraalfabetislebihbesardaripadakatayang beradadalamhalaman,pindahlahkehalamanberikutnyalalukerjakankembali langkah2. 5. JikakatayangsedangAndacari,secaraalfabetislebihkecildaripadakatayang beradadalamhalaman,pindahlahkehalamansebelumnyalalukerjakankembali langkah2. JikaAndasudahmenemukanduakatayang adjacent (salingmengiringi,contohnya; kata fakta dengan faktor)disuatuhalamandalamkamustetapiAndatidakmendapati katayangAndacari(misalnya; fakto)yangseharusnyaterletakdiantaraduakataitu, AndabisamenyimpulkanbahwakatayangAndacaritersebuttidaktercantumdalam kamusitu.SatusatunyaalternatifyangmungkinterjadiadalahkatayangsedangAnda 252
cari tidak berada dalam berkas kamus tersebut, tapi ini justru kontradiktif dengan asumsiyangada;bahwakatakatasudahtersusundalamkeadaanterurutalfabetis. Dalamkasustumpukankartuini,jikakitatahubahwakartukartutersebutberadadalam posisiyangterurut,kitabisamenulismetodefindCardyanglebihcepat.Caraterbaik untukmenulis bisectionsearch adalahdenganmenggunakanteknikrekursif.Halini terjadi karena bisection sebenarnyamerupakansesuatuyangsecaraalamiah bersifat rekursif. Trik yang digunakan adalah dengan cara menulis sebuah metode findBisect yang menggunakan dua indeks sebagai parameter, yakni low dan high, yang akan mengindikasikansegmen/zonadariarrayyangakandikenaipencarian(termasukdua parameteritusendiri,lowdanhigh). 1. Untukmencarididalamarray,pilihlahsebuahindeksdiantara low dan high (berilahnamamid)lalubandingkandengankartuyangsedangAndacari. 2. JikaAndatelahmenemukannya,hentikanpencarian. 3. Jikakartuyangberadadalam mid lebihtinggidaripadakartuyangAndacari, carilahkartutersebutdidaerahdalamintervalantaralowhinggamid1. 4. JikakartuyangberadadalammidlebihrendahdaripadakartuyangAndacari, carilahkartutersebutdidaerahdalamintervalantaramid1hinggahigh. Langkah3dan4kelihatansepertisesuatuyangbersifatrekursif.Berikutiniadalah implementasinyadalamkodeJava: public static int findBisect card,intlow,inthigh){ intmid=(high+low)/2; intcomp=compareCard(deck[mid],card); (Card[] deck, Card
253
if(comp==0){ returnmid; }elseif(comp>0){ returnfindBisect(deck,card,low,mid1); }else{ return findBisect (deck, card, mid+1, high); } } Ketimbang memanggil metode compareCard tiga kali, saya lebih memilih untuk memanggilnyasekalilalumenyimpanhasilnya. Meskipunkodeinimerupakaninti(kernel)daribisectionsearch,tetapikodeinimasih menyisakansesuatuyangjanggal.Dalamkodediatas,terlihatbahwajikakartuyang kitacaritidakberadadidalamtumpukan,metodeiniakanberekursiselamanya.Kita membutuhkan sebuah cara untuk mendeteksi kondisi ini dan mengatasinya dengan cepat(misalnyadengancaramengembalikannilai1). Cara termudah untuk menyatakan bahwa kartu Anda tidak berada dalam tumpukan adalah jika memang benarbenar tidak ada kartu lagi dalam tumpukan. Kondisi ini terjadiketika high lebihrendahdaripada low. Sebenarnya,masihadakartudidalam tumpukan,itupasti,namunyangsayamaksudkandisiniadalahbahwatidakadakartu didalamsegmentumpukanyangtelahdiindikasikandenganlowdanhigh. Dengantambahanbarissepertidibawahini,metodeiniakanbekerjadenganbaik: public static int findBisect card,intlow,inthigh){ System.out.println(low+","+high); if(high<low)return1; 254 (Card[] deck, Card
intmid=(high+low)/2; intcomp=deck[mid].compareCard(card); if(comp==0){ returnmid; }elseif(comp>0){ returnfindBisect(deck,card,low,mid1); }else{ high); } } return findBisect (deck, card, mid+1,
Sayamenambahkansebuahpernyataanprintdiawalmetodeagarsayabisamemantau urutanpemanggilanrekursifyangterjadisekaligusmeyakinkandirisayasendiribahwa metodeiniakansampaikebasecase. Sayamencobakodeberikutini: Cardcard1=newCard(1,11); System.out.println 51)); Lalusayamendapatkanhasilsebagaiberikut: 0,51 0,24 13,24 19,24 22,24 23 255 (findBisect (deck, card1, 0,
Kemudiansayabuatsebuahkartuyangtidakberadadidalamtumpukan,yaknikartu permatabernomor15.Sayamencobauntukmencarinya,lalusayamendapatkanhasil sepertiini: 0,51 0,24 13,24 13,17 13,14 13,12 1 Ujicobainibelummembuktikanbenartidaknyaprogramini.Bahkantidakdiketahui berapajumlahujicobayangharusdilakukanuntukmemastikan kebenaranprogram ini.Dilainpihak,denganmelihatbeberapacontohkasussekaligusmempelajarikode tersebut,mungkinAndabisameyakinkandiriAndasendiri. Jumlahpemangilanrekursifyangterjadibisadibilangrelatifkecil,antara6atau7.Ini berarti bahwa kita hanya perlu memanggil compareCard sebanyak 6 atau 7 kali. Bandingkan dengan 52 kali kemungkinan pemanggilan jika kita menggunakan pencarianlinear.Secaraumum, bisectionsearch lebihcepatdaripada linearsearch. Bahkanuntukarraydenganukuranyangbesar. Duakesalahanyangseringterjadidalamprogramprogramrekursifadalahkealpaan dalammemasukkan basecase sehinggaprogramtidakakanpernahmenemuipemicu untuk berhenti melakukan pemanggilan. Kesalahan seperti ini akan menyebabkan terjadinya pemanggilan rekursi yang tidak berhingga (infinite recursion). Dalam keadaan seperti ini, Java (secara otomatis) akan mengeluarkan StackOverflowException.
256
11.9 Tumpukandansubtumpukan
MelihatkembaliinterfaceyangdigunakanolehmetodefindBisect
public static int findBisect (Card[] deck, Card card, intlow, int high)
mungkinmasihmasukakaluntukmenganggaptigaparameterdiatas,yakni;deck,low, danhigh,sebagaiparametertunggalyangmenentukansebuahsubdeck.Caraberpikir sepertiinisebenarnyasudahlazimdigunakan,danterkadangsayamenyebutnyasebagai parameter abstrak (abstract parameter). Maksud saya dengan kata 'abstrak' adalah sesuatuyangsecaraliteraltidaktermasukkedalamkodeprogram,tetapidigunakan untukmendeskripsikanfungsidariprogramdalamlevelyanglebihtinggi. Sebagaicontoh,ketikaAndamemanggilsebuahmetode,lalumelewatkansebuaharray denganbatasanberupavariabellowdanhighkedalamnya,makatidakakanadayang dapat mencegah metode terpanggil untuk mengakses bagianbagian dari array yang berada di luar batas. Jadi, Anda sebenarnya tidak mengirim sebuah subbagian dari tumpukan; sebaliknya, Anda benarbenar mengirimkan semua tumpukan. Namun selamasipenerimabermainsesuaidenganaturan,sayakiramasihmasukakaluntuk menganggaptumpukandiatassebagaisebuahsubtumpukan,tentunyasecaraabstrak. MasihadasatucontohlagitentangabstraksisepertiiniyangmungkinbisaAndatemui dalam subbab 9.7, yakni ketika saya menyebutnyebut mengenai struktur data yang kosong. Alasan saya menggunakan tanda petik untuk kata kosong adalah untuk menyiratkankepadaAndabahwakatakosongdisitusebenarnyatidaklahterlalutepat. Semuavariabelsebenarnyamemilikinilaisepanjangprogramtersebutberfungsi.Ketika Anda menciptakan variabelvariabel tersebut, semua sudah diberi dengan nilainilai bawaan(default).Jadi,sejatinyatidakadasatuobjekyanglayakdisebutsebagaiobjek yangkosong. 257
Tapijikasebuahprogrambisamenjaminbahwanilaiterbarudarisebuahvariabeltidak pernah dibacasebelumditulis,maka nilai terbarutersebuttermasuk irrelevan. Oleh karenaitu,secaraabstrak,dalamkondisisepertiini,kitabisasajamenganggapvariabel tersebutsebagaivariabelyangkosong. Caraberpikirsepertiini,dimanasebuahprogramdipersepsikanmelebihi(beyond)apa yangbisaditulismerupakansalahsatubagianpentingdalamkerangkaberpikirpara ilmuwan komputer (computer scientist). Terkadang, kata abstrak terlalu sering digunakan. Saking seringnya, sampaisampai ia sering kehilangan maknanya dalam berbagai konteks kalimat. Walaupun begitu, abstraksi merupakan ide utama dalam duniailmukomputer(sebagaimanajugaterjadidibidangbidanglainnya). Definisi abstraksi yang lebih umum adalah sebagai berikut; suatu proses yang bertujuanuntukmemodelkansebuahsistemkompleksdenganmenggunakandeskripsi sederhanaagardapatmenekandetaildetailyangtidakpentingpadasaat menangkap perilakuperilakuyangrelevan.
11.10 DaftarKataKata
Istilah encode Shallowequality Deepquality Abstract parameter abstraction Arti Merepresentasikansatuhimpunan/setnilaidengansatusetnilai lainnyamenggunakanpemetaanantarakeduanya. Kesamaanacuan.Duapengacu(references)menunjukkeobjek yangsama. Kesamaan nilai. Dua pengacu (references) yang menunjuk ke objekyangmemilikinilaiyangsama. Satu setparameter yang beraksi bersamasama sebagai sebuah parameter. Prosesmenginterpretasi/memaknaisebuahprogram(atausesuatu 258
yang lain) dengan pemaknaan yang lebih tinggi daripada apa yangdirepresentasikansecaraliteraldidalamkode.
11.11 Latihan
Latihan11.2 Bayangkanlah sebuah permainan kartu yang tujuannya adalahuntuk mengumpulkan kartukartudenganjumlahtotalsamadengan21.Skortotaluntuksetiappemainadalah skor totaldarisemuakartu yangadadalamgenggamantanganpemain.Skoruntuk masingmasingkartu adalahsebagai berikut:kartu As bernilai 1,semua kartuyang bergambar(Jack,Queen,King)bernilai10,sementarakartukartuyanglaindiberinilai sesuaidenganperingkatnya.Contoh:pemainyangmemegangkartuAs,10,Jack,dan3 memilikiskortotalsebesar1+10+10+3=24. TulislahmetodehandScoreyangmenggunakansebuaharrayberisikartukartusebagai argumen. Nilai yang akan dikembalikan adalah skor total dari kartukartu tersebut. Peringkatperingkatkartuyangdigunakanharusberdasarkanpadapemetaanyangada dalamsubbab11.2,dengankartuAssebagaikartuyangbernilai1. Latihan11.3 MetodeprintCardyangadadalamsubbab11.3menggunakansebuahobjekCarddan mengembalikansebuahstringyangmerepresentasikankartuyangdiminta. BuatlahsebuahmetodekelasuntukkelasCarddengannamaparseCard.Metodeini menggunakansebuahStringsebagaiargumendanmampumengembalikankartuyang terkaitdenganStringtersebut.AndabisamengasumsikanbahwaStringtersebutberisi namadarisebuahkartudalamformatyangvalidsepertiyangsudahdihasilkanoleh metodeprintCard.
259
Dengankatalain,stringituakanberisisatuspasidiantaravariabelrankdankataof, dandiantarakataofdenganvariabelsuit.Jikastringitutidakberisinamakartuyang legal,makametodeakanmengembalikanobjekberisinull. Tujuan dari latihan ini adalah untuk mengulang konsep tentang parsing dan mengimplementasikan sebuah metode yang dapat memparse suatu string yang ditentukan. Latihan11.4 Tulislahsebuahmetode,suitHist,yangmenggunakansebuaharrayberisikartukartu sebagai parameter dan mengembalikan sebuah histogram dari kelompokkelompok kartuyangberadadigenggamantanganseorangpemain.SolusiyangAndagunakan hanyabolehmenelusuriarraysebanyaksatukalisaja,tidaklebih! Latihan11.5 Tulislah sebuah metode isFlush yang menggunakan sebuah array berisi kartukartu sebagaisebuahparameterdanmampumengembalikannilaiTruejikakartukartuyang sedang dipegang berstatus flush, dan False jika sebaliknya. Flush adalah sebuah keadaan ketika seorang pemain mempunyai lima atau lebih kartu yang berasal dari kelompokyangsama.
260
Namavariabelinstannyaadalahcards.Namainidigunakanagarkitabisamembedakan antaraobjek Deck denganarrayberisi Card yangdikandungnya.Berikutiniadalah diagramkeadaanyangmenunjukkankeadaanobjek Deck ketikatidakadasatupun kartudimasukkankedalamnya.
261
Sepertibiasa,konstruktorakanmenginisialisasivariabelinstan,tapidalamkasusini, konstruktormenggunakanperintahnewuntukmembuatsebuaharrayyangberisikartu kartu. Meskipun begitu, konstruktor ini tidak membuat kartu yang bisa masuk ke dalamnya. Untuk melakukannya, kita akan menulis konstruktor lain yang akan membuatsebuahtumpukanberisi52kartulalumengisinyadenganobjekobjekCard: publicDeck(){ cards=newCard[52]; intindex=0; for(intsuit=0;suit<=3;suit++){ for(intrank=1;rank<=13;rank++){ cards[index]=newCard(suit,rank); index++; } } }
PerhatikankemiripanmetodediatasdenganmetodebuildDeck.Bedanya,disinikita harus sedikit mengubah sintaksnya agar bisa digunakan sebagai konstruktor. Untuk memanggilnya,kitaakanmenggunakanperintahnew: Deckdeck=newDeck(); Sekarang, karena kita sudah mempunyai kelas Deck, kita bisa meletakkan semua metode yang terkait dengan Deck di dalam definisi kelas Deck. Bila kita melihat kembali semua metode yang sudah kita tulis sejauh ini, salah satu calon metode 262
(kandidat) yang bisa dimasukkan ke dalam definisi kelas adalah metode printDeck (subbab11.7). Inilah metodetersebut setelah ditulisulang. Hal ini dilakukan agar metode ini bisa berfungsiketikadipakaiolehobjekDeck: publicstaticvoidprintDeck(Deckdeck){ for(inti=0;i<deck.cards.length;i++){ Card.printCard(deck.cards[i]); } }
Sesuatuyangpalingjelasharusdigantiadalahtipeparameternya,dariCard[]menjadi Deck. Perubahan kedua adalah bahwa sekarang kita tidak bisa lagi menggunakan perintah deck.length untukmendapatkanpanjangarray.Haliniterjadikarena deck sekarangmerupakanobjekdari Deck, bukansebuaharraylagi. deck memangberisi array, tapi dia sendiri bukanlah sebuah array. oleh karena itu, kita harus menulis perintahdeck.cards.lengthuntukmengekstrakarraydariobjekDeckuntukkemudian mengambilukuranarraytersebut. Untuk alasan yang sama, kita harus menggunakan perintah deck.cards[i] untuk mengaksessebuahelemenmilikarray, bukan dengan perintah deck[i]. Perubahan terakhiradalahbahwapemanggilanprintCardharusdilakukansecaraeksplisit.Halini sebagai bukti bahwa metode ini memang benarbenar didefinisikan di dalam kelas Card. Untukmetodemetodeyanglainnya,masihtidakjelasapakahmerekaharusdimasukkan kedalamkelasCardataukahDeck.Sebagaicontoh,findCardmenggunakanargumen yang terdiri dari sebuah Card dan Deck. Oleh karena itu, Anda sebenarnya bisa
263
meletakkanmetodeinikedalamsalahsatukelasyangdisebutkan.
12.2 Shuffling
Untuk permainanpermainan kartu yang sering dimainkan, Anda harus mampu melakukan pengacakan (kocok) satu tumpukan kartu. Kegiatan ini disebut dengan shuffling.Dalamsubbab10.6kitatelahmelihatcaramembuatbilanganacak,tapiAnda mungkinmasihbingunguntukmengimplementasikannyakedalampermainankartu. Satu kemungkinan yang bisa diambil adalah dengan menggunakan cara kita (baca: manusia) ketika mengacak kartu. Umumnya, pengacakan dilakukan dengan cara membagitumpukankartukedalamduabagian.Setelahitu,kitaakanmenyusunulang tumpukanitudenganmengambilsatukartusecaraacakdariduatumpukantersebut. Karenamanusiatidakbisamengacakdengansempurna,setelah7kalipengulangan, biasanya urutan kartu dalam tumpukan menjadi tampak seperti benarbenar tidak beraturan. Pun begitu dengan sebuah program komputer, setelah 8 kali melakukan pengacakan, urutan kartu dalam tumpukan justru kembali ke dalam posisi semula. Untuk mendiskusikan hal seperti ini, silahkan mengunjungi http://www.wiskit.com/marilyn/craig.htmlatauAndabisamencarinyadimesinpencari menggunakankatakunciperfectshuffle. Algoritmapengacakanyanglebihbaikadalahdengancaramenelusuritumpukankartu satukaliuntukkemudianmemilihduakartulalumenukarnyadalamtiapperulangan. Berikutiniadalahringkasancarakerjaalgoritmaini.Untukmendeskripsikanprogram ini, saya akan menggunakan kombinasi antara pernyataanpernyataan dalam Java dengankatakatadalambahasaalamiah(baca:bahasayangkitagunakanseharihari). Inilahyangdisebutdenganpseudocode: for(inti=0;i<deck.length;i++){ //pilihlahsebuahbilanganacakdiantaraidan 264
// deck.cards.len
gth
// tukarkan kartu urutan ke idengan kartu yang sudah // terpilih secara acak.
} Halpositifketikamenggunakanpseudocodesepertidiatasadalahbahwaterkadangkita dapatmelihatmetodeyangakankitabutuhkandenganlebihjelas.Dalamkasusini,kita membutuhkanmetodesepertirandomInt,yangdapatmemilihbilanganbertipeinteger secaraacakdidalamintervalantaravariabellowdanhigh.Selainitu,metodeinijuga mampumengambilduaindekslalumenukarkartuyangberadapadaposisiindeksyang terpilih. Anda mungkin dapat menulismetode randomInt dengan melihat subbab 10.6, tapi Andajugaharushatihatiterhadapindeksyangdihasilkan,karenamungkinsajaindeks tersebutkeluardaribatasaninterval. Andajugabisamembuatmetode swapCard sendiritentunya.Satusatunyatrik yang akanAndagunakanadalahapakahAndahanyaakanmenukarreferensiyangmenunjuk keposisikartuatauAndajustruakanmenukarjugaisidarikartukartutersebut.Pilihan AndaakansangatmenentukankecepatanprogramyangAndabuatsecarakeseluruhan. Sayaakanmeninggalkanimplementasimasalahinisebagailatihan.
12.3 Pengurutan(Sorting)
Karena sebelumnya kita telah mengacakacak tumpukan kartu, sekarang kita membutuhkan suatu cara untuk menempatkan semuanya kembali ke posisi terurut. Ironisnya,adasebuahalgoritmauntukmelakukanpengurutanyangsangatmiripdengan pengacakan.Algoritmainiseringdisebut selectionsort. Disebutdemikian karenaia 265
bekerja dengan cara menelusuri array secara berulangulang lalu memilih kartu terendahdalamsetiapperulangan. Padaperulanganpertama,kitamenemukankartuterendah(thelowest)lalumenukarnya dengankartuyangberadadiposisike0.Padaperulanganberikutnya,yaituyangkei, kitaakanmendapatkankartuterendahdisebelahkananilalumenukarnyadengankartu diindeksyangkei. Berikutinimerupakanpseudocodedariselectionsort: for(inti=0;i<deck.length;i++){ // temukan kartu terendah yag berada dalam i atau //yangberadadidaerahsebelahkanannya // tukarlah kartu urutan kei dengan kartu terendah } Lagilagi, pseudocode akan menolong kita dengan memakai rancangan helper methods.Dalamkasusini,kitabisamenggunakanswapCardskembali,jadikitahanya membutuhkan satu buah metode lagi, yakni findLowestCard. Metode ini membutuhkansebuaharrayberisi kartukartu dansebuahindeks tempatdimana ia pertamakalimelakukanpencarian. Sekalilagi,sayaakanmeninggalkanimplementasinyakhususuntukpembaca.
12.4 Subtumpukan(Subdecks)
Apayangharuskitalakukanuntukmerepresentasikankartukartuyangberadadalam
266
genggamantanganseorangpemain(Hand)ataubeberapabentuksubsetlaindarisatu tumpukankartuyangpenuh?Kemungkinanpertamaadalahdengancaramenulissebuah kelasbarudengannama Hand,yangmungkinakanmewarisisifatsifatkelas Deck. Kemungkinanlainnya,yangakansayatunjukkandisini, adalahmerepresentasikan HandmenggunakansebuahobjekDeckyangjumlahnyakurangdari52kartu. Kitamungkinmembutuhkansebuahmetode,yaitusubdeck,yangmenggunakansebuah Deckdansekumpulanindeks.MetodeiniakanmengembalikansebuahDeckbaruyang berisisubsetdarikartukartuyangtelahditentukan: public static Deck subdeck (Deck deck, int low, int high){ Decksub=newDeck(highlow+1); for(inti=0;i<sub.cards.length;i++){ sub.cards[i]=deck.cards[low+i]; } returnsub; }
Ukuran subdeck adalah highlow+1. Hal ini terjadi karena kita juga akan mengikutsertakan kartu terendahdankartu tertinggi. Proseskomputasisemacamini bisa menimbulkan kebingungan, dan juga bisa membawa kita ke dalam error yang termasuk offbyone error. Membuat gambar atau visualisasi merupakan cara yang ampuhuntukmenghindarinya. Karena kitamenyediakansebuahargumendenganperingkat new,makakonstruktor yangdipanggilakanmenjadiyangpertama,yanghanyamengalokasikanarraytapitidak mengalokasikankartuapapun.Didalamperulangan for,subtumpukansubtumpukan akandibuatbesertasalinanreferensiyangadadalamtumpukannya. 267
Berikut ini merupakan diagram keadaan sebuah subtumpukan yang dibuat menggunakanparameter low=3danhigh=7.Hasilnyaadalahsebuah handberisi5 kartu yang saling berbagi referensi dengan tumpukan utamanya; Anda dapat menganggaphandtersebutsebagainamaaliasdaritumpukan.
12.5 PengacakandanPembagianKartu(ShufflingandDealing)
Dalamsubbab12.2sayamenulispseudocodeuntukalgoritmapengacakan.Anggaplah saat ini kita mempunyai sebuah metode dengan nama shuffleDeck. Metode ini menggunakan sebuah tumpukan sebagai argumen lalu mengacaknya. Kita akan mengacaktumpukandengancarasepertiberikut: Deckdeck=newDeck(); 268
shuffleDeck(deck); Kemudian, untuk membagi/mendistribusikan kartu ke beberapa hand lain, kita bisa menggunakansubdeck: Deckhand1=subdeck(deck,0,4); Deckhand2=subdeck(deck,5,9); Deckpack=subdeck(deck,10,51); Kodeiniakanmenempatkan5kartudihandpertama,5kartuberikutnyadihandyang lain,dst. PadasaatAndaberpikirmengenaiprosesbagibagikartu(dealing),apakahAndajuga berpikirmengenaipembagiankartuyangharusdilakukansecarasatupersatuuntuk setiappemain,denganteknikroundrobin,laiknyapermainankartudalamdunianyata? Sayasempatkepikiranjugatentangini,tapikemudiansayamenganggapnyasebagai sesuatuyangtidakterlalupentingketikaharusdiimplementasikankedalamprogram komputer.Teknik roundrobin digunakanuntukmenghindaripengacakanyangtidak sempurna sekaligus kecurangan yang mungkin dilakukan oleh sang pembagi kartu (dealer).TetapiAndatidakusahkhawatir,isudiatasbukanlahmasalahpentingdalam duniakomputer. Contohinidapatmenjadisebuahperingatanyangbergunaterhadapsalahsatumetafora berbahaya dalam dunia rekayasa (engineering): terkadang kita memaksa komputer untukmengerjakanhalhaltidakperluyangmemangberadadiluarkemampuannya, ataumengharapkankemampuankemampuandarikomputeryangsebenarnyamemang tidakdimilikinya.Inisemuaterjadikarenakitatelahmelebihlebihkansebuahmetafora jauhdiatasambangbatasnyasendiri.Berhatihatilahterhadappenggunaananalogiyang salah.
269
12.6 Mergesort
Dalamsubbab 12.3,kitatelahmelihatsebuahalgoritma pengurutansederhanayang akhirnya malah menimbulkan ketidakefisienan bagi program itu sendiri. Untuk mengurutkandatasebanyak n item,algoritmainiharusmenelusuriarraysebanyak n kali.Danuntuksetiappenelusuran,dibutuhkanwaktusejumlahn.Olehkarenaitu,total waktuyangdibutuhkandalamsatupemrosesanlengkapadalahn2. Dalam bab ini saya akan memberikan sebuah algoritma yang lebih efisien, yakni mergesort.Untukmengurutkannitem,mergesortmembutuhkanwaktusebanyaknlog n. Mungkin tidak terlalu bagus, tapi jika nilai n bertambah semakin besar, maka perbedaanantara n2 dan nlogn menjadisangatsignifikan.Cobalahdenganbeberapa nilainlalulihathasilnya. Ide dasar dari mergesort adalah sebagai berikut: jika Anda mempunyai dua subtumpukanyangkeduanyasudahdalamposisiterurut,makaAndaakanlebihmudah (jugacepat)untukmenggabungkannyakedalamsatutumpukantunggalyangterurut. Cobalahbeberapahaldibawahini: 1. Buatlahduasubtumpukanyangmasingmasingterdiridari10kartukemudian urutkanlahkeduanyasehinggaketikakeduanyasalingberhadaphadapan,kartu terendahakanberadadiposisiteratas.Letakkankeduasubtumpukantersebut tepatdidepanmukaAnda. 2. Bandingkankartuteratasdarimasingmasingsubtumpukanlalupilihlahyang terendah di antara keduanya. Tukarkan posisi keduanya lalu tempatkan keduanyakedalamtumpukanbaruyangakanmenjaditumpukantunggal. 3. Ulangi langkah kedua sampai kartukartu di kedua subtumpukan itu habis. Kartukartuyangsudahdikenaiprosespadalangkahkeduaadalahkartukartu yangtelahdigabungkedalamsatutumpukantunggal. 270
Hasilnyaadalahsebuahtumpukantunggalyangteruruttentunya.Berikutinimerupakan pseudocodealgoritmadiatas:
public static Deck merge (Deck d1, Deckd2) { /* buat sebuah tumpukan menampung semua kartu dari duasubtumpuk Deck result th); an */ (d1.cards.len gth + yang cukup besar untuk
= new Deck
d2.cards.leng
/*gunakan indeks iuntuk mengetahui posisi kita dalam tumpukan yang pertama, dan indeks j untuk tumpukan kedua */ int i=0; int j=0; //indeks kdigunakan untuk menelusuri tumpukan result for (intk =0; k<result.car // jika d1 kosong, d2 menang; jika d2 kosong, d1 menang; // jika dua kondisi ini tidak terpenuhi, bandingka n kartu kartu yangberada dalam duasubtumpuka // masukkan pemenangnya } return result; n ke dalam tumpukan yang baru ds.len gth; k++) {
271
Caraterbaikuntukmengujimetode merge adalahdenganmembuatsebuahtumpukan lalu mengacaknya, gunakan subtumpukan untuk membuat dua hand dengan jumlah kartu yang sedikit, lalu gunakan algoritma yang ada di bab sebelumnya untuk mengurutkansetiapsubtumpukanmilik hand.Setelahselesai,Andabisamelewatkan keduasubtumpukanmilik hand kemetode merge untukmelihatapakahmetodeini berhasilataujustrusebaliknya. Jika Anda melihat metode merge ini berhasil dengan baik, cobalah implementasi sederhanadarimetodemergeSortberikutini: publicstaticDeckmergeSort(Deckdeck){ //temukantitiktengahtumpukantersebut //bagilahtumpukanitumenjadiduasubtumpukan //urutkankeduasubtumpukanmenggunakan //hasilnya } Nah,kalauAndajugaberhasilmengimplementasikankodediatasdenganbenar,halhal yangmenarikakansegeraterjadi!Sesuatuyangajaibdalam mergesort adalahfakta bahwateknikinimelakukanprosesyangbersifatrekursif.DisaatAndamengurutkan subtumpukansubtumpukanitu,Andatidakperlulagirepotrepotmemanggilmetode lama yang lebih lambat. Anda cukup menggunakan metode mergeSort milik Anda sendiriyanglebihkerendidalamnya. Bukanhanyasoalpenggunaanpemikiran/ideyangbagus,langkahdiatassebenarnya kitalakukanagarkitadapatmencapaikinerjayangsebelumnyatelahsayajanjikan. sortDeck //gabungkanduasubtumpukanitulalukembalikan
272
Agar dapat berfungsi dengan baik, Anda harus menambahkan base case ke dalam programAndaagarprogramitutidakmerekursifselamanya.Basecaseyangsederhana adalahsubtumpukanyangberisi0atau1kartu.JikamergeSortmenerimasubtumpukan sepertiini,iabisamengembalikansubtumpukanitutanpamengubahnyasamasekali karenasubtumpukansepertiitutentuberadadalamposisiyangsudahterurut. Berikutiniadalahversirekursifdarimergesort: publicstaticDeckmergeSort(Deckdeck){ //ifthedeckis0or1cards,returnit //findthemidpointofthedeck //dividethedeckintotwosubdecks //sortthesubdecksusingmergesort //mergethetwohalvesandreturntheresult } Sepertibiasa,adaduaparadigmapengembanganuntukprogramyangbersifatrekursif; AndabisamelihatnyadarisisikeseluruhanprosesyangakandieksekusiatauAndajuga bisamelihatnyasebagaisesuatuyangbisadipilahpilahmenjadibagianbagiankecil. Saya telah mencontohkan contohcontoh di atas agar Anda bisa mempraktikkan paradigmakedua. KetikaAndamenggunakan sortDeck untukmengurutkansubtumpukansubtumpukan, Andatentutidakmerasaharusmengikutidanmemperhatikankeseluruhanprosesyang dieksekusi bukan? Anda hanya perlu menganggap bahwa metode sortDeck akan bekerja dengan baik karena Anda telah memeriksanya (debug) sebelum digunakan. Well,sesuatuyangharusAndalakukanjikainginmelihatmergeSortbersifatrekursif adalahdenganmenggantisatualgoritmapengurutandenganalgoritmalainnya.Saya kiraAndatidakmempunyaialasanyangcukupbagusuntukmelihatprograminidengan 273
carayanglain. Sebenarnya, ketika Anda menulis programprogram bersifat rekursif, Anda harus memberikanperhatianlebihpadasaatmembuatbasecase.Basecasetersebutharuslah benardanbisaberfungsidengantepat.Selainfaktorini,membuatversirekursifdari suatuprogramtentunyatidakakanmenjadimasalahlagiuntukAnda.Semogaberhasil!
12.7 DaftarKataKata
Istilah pseudocode Arti Suatu teknikuntukmerancangprogram komputerdengan cara membuat deskripsi singkat (rough drafts) program tersebut menggunakan kombinasi antara bahasa natural (bahasayangkitagunakanseharihari)denganbahasaJava Helpermethod Metode kecil yang umumnya tidak melakukan sesuatu secarasignifikanuntukdirinyasendiritetapijustrumalah menolongmetodelainagarmetodetersebutdapatberfungsi lebihbaik
12.8 Latihan
Latihan12.1 Tulislah sebuah versi metode findBisect yang menggunakan sebuah subtumpukan sebagai argumennya ketimbang menggunakan sebuah tumpukan dan interval indeks (lihatsubbab11.8).Versimanayangkirakiralebihrawandenganerror?Versimana yangmenurutAndalebihefisien? Latihan12.2 Dalam versi kelas Card sebelumnya, sebuah tumpukan diimplementasikan sebagai 274
sebuaharrayyangberisiCard.Contoh;ketikakitamelewatkansebuahdecksebagai parameter,tipeparameteryangsebenarnyaadalahCard[]. Dalambabini,kitatelahmengembangkansebuahrepresentasialternatifuntuksebuah tumpukan,yaitusebuahobjekdengannamaDeckyangmengandungsebuaharrayberisi kartukartu sebagai variabel instannya. Dalam latihan ini, Anda akan mengimplementasikansebuahrepresentasibaruuntuksebuahtumpukan. a) Buatlah file tambahandengannama Deck.java kedalamprogramAnda. File ini akanberisisemuadefinisimengenaikelasDeck. b) Buatlah sebuah konstruktor untuk kelas ini seperti yang telahditunjukkan dalam subbab12.1. c) DiantarametodemetodeyangadadidalamkelasCard,pilihlahmetodeyangsesuai dan dapat dijadikan sebagai anggota kelas Deck yang baru. Pindahkan metode metode yang Anda pilih tersebut ke dalam kelas baru itu lalu buatlah beberapa perubahansignifikanagarprogramAndabisadicompile dandieksekusikembali denganbenar. d) Lihatkembaliprogramtersebutkemudianidentifikasilahsetiaptempatketikasebuah array yang berisi Card digunakan untuk merepresentasikan sebuah tumpukan. Modifikasilah keseluruhan program sehingga program akan menggunakan objek Deck daripadayanglainnya.Andabisamelihatmetode printDeck dalamsubbab 12.1sebagaicontoh. Perubahaninisebaiknyadilakukandengansistem permetode.Jadi,disiniAnda dimintauntuklangsungmemeriksaperubahanyangterjadisetiapkaliAndatelah selesaimemodifikasisebuahmetode.Disisilain,jikaAndamemangbenarbenar yakin dengan apa yang Anda lakukan, Anda juga bisa menggunakan perintah searchandreplace. 275
Latihan12.3 Tujuan latihan ini adalah untuk mengimplementasikan algoritma pengacakan dan pengurutanyangtelahdipelajaridalambabini. a) TulislahmetodeswapCardsyangmenggunakansebuahtumpukan(arrayyangberisi kartukartu)danduaindeks.Metodeiniberfungsiuntukmenukarkartukartuyang beradadalamdualokasitersebut. PETUNJUK:Metodeiniharusmenukarreferensiyangmengacukeduakartuitu, bukan isinya. Cara ini tidak hanya memiliki kinerja lebih cepat, tapi juga dapat memudahkan kita ketika harus berhadapan dengan kasus di mana kartukartu tersebutsedangdisamarkan(aliasing). b) Tulislahmetode shuffleDeck yangmenggunakanalgoritmadisubbab12.2.Anda mungkininginmemanfaatkanrandomIntyangadadilatihan10.2. c) Tulislah metode findLowestCard yang menggunakan compareCard untuk menemukan kartu terendah di dalam interval kartukartu yang diberikan (antara lowIndexhinggahighIndex). d) TulislahmetodesortDeckyangmenyusunsatutumpukankartudarikartuterendah hinggayangtertinggi. Latihan12.4 Untukmembuathidupparapengacakdanpembagikartu(cardcounter)semakinsulit, sekarang banyak kasino yang menggunakan mesin pengacak yang mengacak kartu secara secara naiksatu per satu (incremental shuffling). Ini berarti, setiap selesai membagikartuuntuksatupemain,kartuyangtelahdibagitersebutakandikembalikan lagi ke dalam tumpukan. Kartu ini dikembalikan lagi ke dalam tumpukan tanpa melakukanpengacakanulang.Jadi,mesinhanyamemasukkankartuitukeposisilain secaraacak. 276
Tulislah metode incrementalShuffle yang menggunakan sebuah Deck dan sebuah Card sebagai argumen. Metode ini berfungsi untuk memasukkan atau menyisipkan kartukedalamtumpukandiposisiyangacak.Berikutinimerupakancontohsebuah incrementalalgorithm. Latihan12.5 Tujuan latihan ini adalah untuk menulis sebuah program yang dapat membuat permainanpokeruntukbeberapa hand secaraacaklalumengelompokkannya.Dengan cara ini, kita dapat memperkirakan probabilitas dari masingmasing hand. Jangan khawatirjikaAndabelumpernahmemainkannya;sayaakanmemberitahusemuayang perluAndaketahui. a) Untuk pemanasan, tulislah sebuah program yang menggunakan shuffleDeck dan subdeck untukmembuatdanmencetakmasingmasinglimakartuyangberadadi empathandpemainpokeryangsudahdiacak.Bagaimana,sudahmengerti?Berikut iniadalahbeberapastatus hand dalampermainanpoker,dalamposisiyangterurut naik: pair:duakartudenganperingkat(rank)yangsama twopair:duapasangkartudenganperingkatyangsama threeofakind:tigakartudenganperingkatyangsama straight:limakartudenganperingkatyangberurutan flush:limakartudengankelompok(suit)yangsama fullhouse:tigakartudengansatuperingkatyangsama,duakartulainnyatidaksama fourofakind:empatkartudenganperingkatyangsama straightflush:limakartuyangperingkatnyaberurutandantergabungdalamsatu kelompokyangsama
277
b) Tulislahmetode isFlush yangmenggunakansebuah Deck sebagaiparameter dan mengembalikannilaibertipebooleansebagaiindikatorapakahhandyangdiperiksa berstatusflushataukahbukan. c) Tulislah sebuah metode isThreeKind yang menggunakan sebuah hand dan mengembalikan sebuah nilai bertipeboolean yang mengindikasikan apakah hand tersebuttermasukThreeOfAKindataukahbukan. d) Tulislahsebuahperulanganyangmenghasilkanbeberaparibu handdanmemeriksa apakahhandhandtersebuttermasukFlushataukahThreeOfAKind. e) Tulislah beberapa metode yang bisa menguji statusstatus hand poker lainnya. Beberapadiantaranyamungkinlebihmudahketimbanglainnya.Mungkinakanlebih baikjikaAndamenulisbeberapahelpermethodyangbisadigunakansecaraumum untukbeberapametodepengujisekaligus. f) Dalambeberapapermainanpoker,masingmasingpemainakanmendapatkantujuh kartu.Dariketujuhkartutersebut,merekadiizinkanuntukmembuatkombinasidari lima kartu saja. Modifikasilah program Anda agar bisa menghasilkan hand yang terdiri dari tujuh kartu sekaligus menghitung ulang probabilitas yang mungkin terjadi. Latihan12.6 Sebagai sebuah tantangan khusus untuk Anda, pikirkanlah sebuah algoritma yang mampumemeriksa wildcard yangterdapatdalam handhand yangsedangbermain. Sebagaicontoh,jikadeucesarewild,iniberartibahwajikaAndamempunyaisebuah kartudenganperingkat2,Andabisamenggunakankartuiniuntukmerepresentasikan kartuapapunyangberadadalamtumpukan. Latihan12.7 TujuanlatihaniniadalahagarAndabisamengimplementasikanmergesort. 278
a) Denganpseudocodeyangadadisubbab12.6,tulislahmetodedengannamamerge. UjilahmetodeinisebelumAndamemasukkannyakedalammetodemergeSort. b) Tulislahversisederhanadari mergeSort,yakniyangmampumembagitumpukan menjadi dua. Gunakan sortDeck untuk mengurutkan kedua bagian tersebut, lalu gunakanmetodemergeuntukmembuatsebuahtumpukanbaruyangsudahterurut. c) Tulislah versi mergeSort yang benarbenar bersifat rekursif. Ingatlah bahwa sortDeck merupakansebuah modifier sementara mergeSort adalahsebuahfungsi. Iniberartibahwakeduanyadipanggildengancarayangberbeda:
sortDeck (deck); // modifies existing deck deck =mergeSort (deck); //replaces old deckwith new
279
Definisiobjek(yangberupakelaskelas)biasanyaberkaitandenganobjekobjek yangberadadidunia nyata. Contoh;di subbab 12.1,pembuatankelas Deck merupakan langkah menuju penggunaan konsep pemrograman berorientasi objek.
Metodemetodeyangdibuatumumnyaberupametodeobjek(yangAndapanggil melaluiobjek)ketimbangmetodekelas(yangbisalangsungAnda panggil). Sejauh ini, semua metode yang kita tulis merupakan metodemetode kelas. Dalambabini,kitaakanmencobamenulisbeberapametodeobjek.
280
Fiturbahasayangsangatterkaitdengansifatpemrogramanberorientasiobjek adalahinheritance.Sayaakanmembahasnyadalambabini.
Akhirakhirini,pemrogramanberorientasiobjekmenjadisangatpopuler,danbahkan ada orang yang menganggapnya sebagai teknik pemrograman yang lebih hebat (superior)ketimbangtekniktekniklainnya.Sayaberharapbahwadenganmenyuguhkan kepadaAndacaramenggunakanbeberapateknikyanglainberartisayatelahmemberi Andaalatuntukmemahamisekaligusmengevaluasikeabsahanklaimdiatas.
12.3 MetodeObjekdanMetodeKelas
AdaduatipemetodedalamJava;metodekelas(classmethod)danmetodeobjek(object method).Sejauhini,semuametodeyangkitatulistermasukkedalamtipemetodekelas. Metodeinibisadikenalidarikeberadaankatakuncistaticyangberadadibarispertama pada tiap metode. Sementara itu, semua metode yang tidak mempunyai static bisa dianggapsebagaimetodeobjek. Meskipunkitabelummenulissatupunmetodeobjek,sebenarnyakitatelahmemanggil beberapa diantaranya. Kapan pun Anda memanggil sebuah metode melalui sebuah objek,makaitulahyangdisebutdenganmetodeobjek.Misalnyametode charAt dan semuametodeyangkitapanggilmelaluiobjekString. Semuayangbisaditulissebagaimetodekelasjugabisaditulissebagaimetodeobjek. Begitu pula sebaliknya.Terkadang, akan tampak lebihalamiah untuk menggunakan salah satunya saja. Sebentar lagi kita akan melihat bahwa metodemetode objek seringkaliterlihatlebihsingkatdanpadatketimbangmetodemetodekelas.
13.3 ObjekTerkini
Ketika Anda memanggil sebuah metode melalui sebuah objek, objek tersebut akan
281
13.4 BilanganKompleks
Untukcontohkasus,sepanjangbabinikitaakanmencobamembuatdefinisikelasuntuk bilangankompleks.Bilangankompleksbanyakdigunakandilingkunganmatematika dan dunia perekayasaan (engineering). Di samping itu, banyak juga perhitungan perhitunganyangmenggunakanaritmetikakompleks. Sebuah bilangan kompleks merupakan hasil penjumlahan antara bilangan real dan bilanganimajiner.Bilanganinibiasanyaditulisdalambentukx+yi,dimanaxadalah bilanganrealnya,sementaraymerupakanbilanganimajinernya.Notasiisendiriadalah representasidariakar1.Olehkarenaitu,i*i=1. Kodeberikutinimerupakandefinisikelasuntuktipeobjekbaru,Complex: classComplex { //instancevariables doublereal,imag; //constructor publicComplex(){ this.real=0.0;this.imag=0.0; }
282
//constructor publicComplex(doublereal,doubleimag){ this.real=real; this.imag=imag; } } HarusnyatidakadayangmengejutkanAndadarilampirankodeini.Variabelvariabel instannyabertipedoubleyangmewakilibilanganrealdanimajiner.Keduakonstruktor di atas termasukjeniskonstruktor yangsudah lazim dipakai:satu konstruktor tidak membutuhkansatuparameterpundanmengassign nilainilai default untukvariabel variabel instan, sementara konstruktor lainnya menggunakan dua parameter yang identikdenganvariabelinstannya.Sepertiyangsudahkitalihatsebelumnya,katakunci thisdigunakanuntukmengacukeobjekyangsedangdiinisialisasi. Didalammain,ataudimanapunkitainginmembuatobjekComplex,kitamempunyai pilihan;untukmembuatobjeknyadahululalumengaturvariabelvariabelinstannyaatau melakukankeduanyasekaliguspadasaatyangbersamaan: Complexx=newComplex(); x.real=1.0; x.imag=2.0; Complexy=newComplex(3.0,4.0);
13.5 FungsifungsidalamBilanganKompleks
Mari kita lihat beberapa operasi yang mungkin akan kita kerjakan untuk mengolah bilanganbilangankompleks.Nilaiabsolutdarisebuahbilangankompleksdidapatdari 283
hasil
x 2 y 2
.Metodeabsadalahfungsimurniyangmenghitungnilaimutlak.Bila
ditulisdalambentukmetodekelas,sepertiinilahkodenya: //classmethod publicstaticdoubleabs(Complexc){ return Math.sqrt (c.real * c.real + c.imag * c.imag); } Versi abs ini menghitung nilai absolut milik c, objek Complex yang diterimanya sebagai parameter. Versi lain dari abs adalah sebuah metode objek; metode ini menghitung nilaiabsolut milik objek terkini (objek yang memanggilmetode). Oleh karenaitu,metodeinitidakakanmembutuhkanparameterapapun. //objectmethod publicdoubleabs(){ returnMath.sqrt(real*real+imag*imag); } Saya menghilangkan kata kunci static untuk mengindikasikan bahwa metode ini merupakanmetodeobjek.Selainitu,sayaakanmenghilangkanparameteryangtidak diperlukan. Di dalammetode, saya bisamengacu ke variabel instan real dan imag dengannamanyatanpaharusmenyertakansuatuobjeksecaraspesifik.Javamengetahui secara implisit bahwa saya sedang mengacu ke variabelvariabel instan milik objek terkini.Jikasayainginmembuatnyabersifateksplisit,sayaakanmenambahkankata kuncithis:
//ob ject met hod publi cdo uble abs (){ ret urn Math .sqr t (t his. real * this. real + this. imag *
284
this. imag ); }
13.6 FungsifungsilainnyadalamBilanganKompleks
Operasilainyangmungkinakankitaperlukanadalahfungsipenjumlahan.Andabisa menjumlahkan bilanganbilangan kompleks dengan menjumlahkan masingmasing bilangandenganpasangannya masingmasing;realdenganrealdanimajinerdengan imajiner.Dalambentukmetodekelas,bentuknyaakansepertiberikut:
publi cst atic Com plex add (Co mple xa, Com plex b){ r etu rnn ewC ompl ex( a.re al+ b.r eal, a.i mag+ b. imag ); }
Untukmemanggilmetodeini,kitaakanmelewatkankeduaoperansebagaiargumen: Complexsum=add(x,y); Dalam bentuk metode objek, metode ini hanya perlu satu argumen yang akan ditambahkankeobjekyangsedangdigunakan(currentobject).
publi cCo mple xad d(C ompl exb ){ r etur nne wCo mple x(r eal+ b. real ,im ag+ b.i mag) ; }
Lagilagi, di sini kita bisa mengacu ke variabel instan milik objek terkini secara implisit,tapiuntukmengacukevariabelinstanmilikobjek b kitaharusmenamaib 285
secaraeksplisitmenggunakannotasititik(dot).Untukmemanggilmetodeini,Andabisa memanggilnya melalui salah satu operan lalu melewatkan operan lainnya sebagai argumen. Complexsum=x.add(y); Daricontohcontohini,Andabisamelihatbahwaobjekterkini(this)bisamengambil alihdarisalahsatuparameter.Karenaalasaninilahobjekterkiniseringjugadisebut sebagaiparameterimplicit.
13.7 Modifier
Seperticontohcontohsebelumnya,kitaakanmelihatmetode conjugate.Metodeini merupakanmetodepengubahyangmentransformasikansebuahbilangan Complex ke bentukkonjugasikompleksnya.Konjugasikompleksdarix+yiadalahxyi. Sebagaimetodekelas,bentuknyaakanmenjadisepertiini: publicstaticvoidconjugate(Complexc){ c.imag=c.imag; } Dalambentukmetodeobjek,kodenyaakanmenjadisepertiini: publicvoidconjugate(){ imag=imag; } Mulaisekarang,Andaharusnyasudahpahambahwamengubahsuatumetodedarisatu bentuk ke bentuk lainnya merupakan proses mekanis. Dengan sedikit latihan, Anda akanmampumelakukannyatanpaharusberpikirpanjangterlebihdahulu.Haliniakan bagus sekali karena Anda memang sudah seharusnya tidak perlu terhambat untuk
286
menulissalahsatudiantaranya. Anda harusakrab dengankeduanyaagar Anda bisa langsungmemilihmanayanglebihcocokdenganoperasiyangsedangAndatulis. Sebagaicontoh,sayaberpikirbahwaaddharusnyaditulissebagaimetodekelaskarena metodeinimerupakanoperasisimetrisdariduaoperan.Andajugabisamenampilkan keduaoperansebagaiparameter.Bagisaya,agakganjilrasanyajikakitamemanggil satu metode melalui sebuah operan lalu melewatkan operan lainnya sebagai argumennya. Disisilain,beberapaoperasisederhanayangdigunakanuntuksatuobjekbisaditulis dengan baik menggunakan metodemetode objek (pun jika metodemetode itu membutuhkanbeberapaargumentambahan).
13.8 MetodetoString
Setiap tipe objek mempunyai sebuah metode, yakni toString yang mampu menghasilkan representasi string dari objek tersebut. Ketika Anda mencetak sebuah objekmenggunakan print atau println,Javaakanmemanggilmetode toString milik objektersebut.Versidefaultmetodeiniakanmengembalikansebuahstringyangberisi tipeobjekbesertasebuahidentifierunik(lihatsubbab9.6).KetikaAndamendefinisikan sebuahtipeobjekyangbaru,Andabisamengoverrideperilaku(behaviour)defaultdari suatumetodedenganmembuatsebuahmetodebaruyangperilakunyasesuaidengan keinginanAnda. BerikutinitampilantoStringdidalamkelasComplex: publicStringtoString(){ returnreal+"+"+imag+"i"; }
287
Tentu saja, tipe kembalian milik toString adalah String. Metode ini tidak membutuhkanparameterapapun.Andabisamemanggil toString dengancarayang sudahbiasakitapakai: Complexx=newComplex(1.0,2.0); Strings=x.toString();
13.9 Metodeequals
Ketika Anda menggunakan operator == untuk membandingkan dua objek, yang sebenarnya Anda maksudkan adalah, apakah dua objek ini merupakan objek yag sama? Itu dia, apakah kedua objek mengacu ke lokasi yang sama dalam memori. Untukkebanyakantipe,definisidiatasbukanlahdefinisiyangtepatuntukmenjelaskan prinsip kesamaan(equality).Sebagaicontoh,duabilangankompleksdianggapsama jikabilanganrealkeduanyasamadanbegitupuladenganbilanganimajinermereka. Merekatidakharusberupaobjekyangsama. KetikaAndamendefinisikansebuahtipeobjekyangbaru,Andabisamembuatdefinisi persamaan sendiri dengan menulis sebuah metode objek, yaitu equals. Untuk kelas Complex,bentuknyaakantampaksebagaiberikut: publicbooleanequals(Complexb){ return(real==b.real&&imag==b.imag); } 288
Transitif:untuksetiapnilaiyangdiacux,ydany,jikax.equals(y)bernilaitrue dany.equals(z)jugabernilaitruemakax.equals(z)jugaharusbernilaitrue.
Konsisten:untuksetiapnilaiyangdiacuxdany,pemanggilanberulangulang x.equals(y) harus bernilai true secara konsisten, atau bernilai false secara konsisten.
Untuksetiapnilaiyangdiacux,x.equals(null)harusbernilaifalse.
13.10 MemanggilSatuMetodeObjekdariMetodeObjekLain
SepertiyangAndaharapkan,JavamengizinkanAndauntukmemanggilsatumetode objek dari metode objek lainnya. Sebagai contoh, untuk menormalisasi bilangan kompleks,Andaakanmembagikeduabagianberdasarkannilaimutlaknya.Sebenarnya masihtidakcukupjelaskenapainibisabermanfaat,inilahkenyataannya. Mari kita tulis metode normalize sebagai sebuah metode objek, lalu membuatnya sebagaimodifier. 289
publicvoidnormalize(){ doubled=this.abs(); real=real/d; imag=imag/d; } Baris pertama akan menemukan nilai mutlak milik objek terkini dengan cara memanggil abs melaluiobjekterkini.Dalamkasusini,sayamenyebutobjekterkini secara eksplisit, meski pun sebenarnya saya juga bisa melewatkannya. Jika Anda memanggilsatumetodeobjekmelaluimetodeobjeklainnya,Javaakanmengasumsikan bahwaAndasedangmemanggilmetodetersebutmelaluiobjekterkini. Latihan13.1 Tulisulanglah normalizeagarmenjadifungsimurni.Lalutulisulanglahmetodeini agarbisamenjadimetodekelas.
13.11 KeganjilandanError
JikaAndamempunyaimetodeobjekdanmetodekelasdalamsatudefinisikelasyang sama,Andajustruakanlebihseringmenjadibingung.Carayanglazimdipakaiuntuk mengelolasuatudefinisikelasadalahdenganmeletakkansemuakonstruktordiawal awalkode,diikutidengansemuametodeobjeklalubarumenuliskansemuametode kelasnya. Andadapatmemilikisebuahmetodeobjekdanmetodekelasdengannamayangsama selamakeduanyatidaksamadalamjumlahdantipeparameteryangdigunakan.Seperti lazimnyasebuah overloading,Javaakanmenentukanversimanayangdipanggiloleh penggunadenganmelihatargumenyangakandilewatkan. Sekarang,karenakitasudahtahuapamaksuddanmanfaatdarikatakuncistatic,Anda 290
mungkinberpendapatbahwa main termasukmetodekelas.,yangjugaberartibahwa tidakadaobjekterkiniketikametodeinisedangdipanggil. Karena objek terkini tidak boleh ada dalam sebuah metode kelas, Anda akan menghasilkan error jika bersikeras menggunakan kata kunci this. Jika Anda mencobanya,Andaakanmendapatkanpesanerroryangberbunyi:Undefinevariable: this.Selainitu,Andajugatidakakanbisamengacukevariabelinstantanpanotasidot dannamaobjeknya.Jikamasihberanimencobanya,Andaakanmendapatkanpesan: Can'tmakeastaticreferencetononstaticvariable.....Pesaninisebenarnyabukanlah pesan error yangbaikkarenamasihmenggunakanbahasayangdiluarstandar.Tapi jika Anda sudah paham apa maksudnya, otomatis Anda juga akan mengerti apa maksudnya.
13.12 Inheritance
Kemampuan suatu bahasa yang paling sering dikaitkan dengan pemrograman berorientasi objek adalah inheritance. Inheritance adalah suatu kemampuan untuk mendefinisikan sebuah kelasbaru yangmerupakanhasil modifikasidari kelasyang sebelumnyatelahdidefinisikan(termasukkelaskelasbuiltin). ManfaatutamadarifituriniadalahagarAndadapatmenambahkanmetodemetodeatau variabelvariabel instan baru ke dalam kelas yang sudah ada tanpa harus memodifikasinya.HalinisangatbergunajikaAndahendakmelakukansesuatuterhadap kelaskelasbuiltinyangmemangtidakbisadiubahubahmeskipunAndasangatingin melakukannya. Disebut inheritance karena kelas yang baru akan mewarisi (inherit) semua variabel instandanmetodeyangadadalamkelasyangsudahadaterlebihdahuluitu.Dengan menggunakan analogi di atas, kelaskelas yang sudah ada/eksis terlebih dahulu itu
291
seringdisebutdengankelaskelasinduk(parentclass).
13.13 Lingkaranyangbisadigambar
Berikut ini merupakan satu contoh inheritance, di sini kita akan mengambil kelas Rectangle yang sudah kita buat sebelumnya lalu kita beri tambahan agar bisa digambar.Kitaakanmembuatsebuahkelasbaruyangbernama DrawableRectangle yangakanmewarisisemuavariabelinstandanmetodemilikkelasRectangle.Ditambah sebuahmetodedrawyangakanmengambilsebuahobjekGraphicssebagaiparameter lalumenggambarlingkaranyangkitainginkan. importjava.awt.*; classDrawableRectangleextendsRectangle{ publicvoiddraw(Graphicsg){ g.drawRect(x,y,width,height); } } Ya,itulahkeseluruhandefinisikelasyangkitamaksud.Barispertamamengimporpaket java.awtyangmenjaditempatdimanaRectangledanGraphicsdidefinisikan. Baris berikutnya mengindikasikan bahwa DrawableRectangle diwariskan dari Rectangle. Kata kunci extends digunakan untuk mengidentifikasi kelas yang kita warisi,yangdalamhalinikitasebutsebagaikelasinduk(parentclass). Sisanyaadalahdefinisidarimetodedraw,yangmengacukevariabelinstanx,y,width dan height.Mungkinakanterkesanganjiljikakitamengacukevariabelinstanyang tidak tampak dalam definisi kelas, tapi ingatlah bahwa mereka sebenarnya sudah diwariskanolehkelasinduk. 292
Untuk membuat dan menggambar sebuah DrawableRectangle, Anda bisa menggunakankodeberikutini: public static void draw (Graphics g, int x, int y, intwidth,intheight){ DrawableRectangle (); dr.x=10;dr.y=10; dr.width=200;dr.height=200; dr.draw(g); } Parameterparameter dalam draw adalah sebuah objek Graphics dan kotak untuk menampilkangambarlingkaran(bukankoordinatkoordinatlingkarantersebut). Lagilagi,mungkinakanterkesanganjilbilamenggunakanperintahnewuntuksebuah kelas yang tidakmempunyai konstruktor. DrawableRectangle mewarisikonstruktor bawaan(default)milikkelasinduknya,jaditidakadamasalahdisana. Kita bisa menset variabel instan milik dr lalu memanggil metodemetode melalui dirinya sendiri dengan cara yang sudah biasa kita lakukan sebelumnya. Ketika kita memanggil grow atau metodemetode lain milik Rectangle melalui dr, Java akan menggunakanmetodeyangsudahdidefinisikandalamkelasinduk. dr = new DrawableRectangle
13.14 HierarkiKelas
DalamJava,semuakelascenderungmemperluasbeberapakelasyangsudahada.Kelas yang paling dasar adalah Object. Kelas ini tidak mengandung variabel instan tapi menyediakanmetodeequalsdantoStringuntukkelaslainnya. Banyak sekali kelas yang memperluas Object, termasuk hampir semua kelas yang 293
sudah kita tulis dan kelaskelas bawaan seperti Rectangle. Semua kelas yang tidak menuliskannamakelasinduknyasecaraeksplisitakanmewarisikelas Object secara default. Bagaimanapunjuga,beberaparantaipewarisanadayanglebihpanjangdariapayang kitaperkirakan.Sebagaicontoh,diAppendixD.6,disitukitamelihatbahwakelasSlate merupakanperluasandarikelasFrame,yangmerupakanperluasandarikelasWindow, lalu berturutturut Container, Component, sampai ke kelas Object. Tidak peduli seberapapanjangrantaipewarisanini,Objectmerupakanindukdarisemuaindukkelas yangada. SemuakelasdalamJavabisadikelolakedalamsebuahsilsilahkeluarga(familytree) yangdisebuthierarkikelas(classhierarchy). Object biasanyamunculdibagianatas, dengan semua anak yang berada di bawahnya. Jika Anda melihat dokumentasi mengenaiFrame,sebagaicontoh,Andaakanmelihathierarkiyangmenyusunsilsilah kelasFrame.
13.15 RancanganBerorientasiObjek
Inheritance merupakanfituryangsangatbagus(powerfull).Beberapaprogramyang seringkali kompleks tanpanya, bisa ditulis secara lugas dan sederhana dengannya. Selainitu,inheritancebisamemfasilitasipemakaianulangsuatukode(codereuse).Ini karenaAndamemilikikesempatanuntukmengkustomisasiperilakukelaskelasbuiltin tanpaharusmengubahnya. Disisilain,inheritancejugadapatmenyebabkansuatuprogramlebihsulitdibaca.Hal ini terjadi jika kodenya ditulis tanpa adanya kejelasan; kapan sebuah metode bisa dipanggil,dimanamencaridefinisinya.Sebagaicontoh,salahsatumetodeyangbisa AndapanggilmelaluiSlateadalahgetBounds.BisakahAndamenemukandokumentasi 294
mengenai metode ini? Saking sulitnya mencari dokumentasi untuk metode ini, terkadangkitamalahberanggapanbahwajanganjangandokumentasinyaterdapatdi indukdariindukdariindukdariindukSlate. Danjanganlupa,banyakhalhalyangbisadikerjakandengankonsepinheritancejuga bisadikerjakansamabaiknya(bahkanlebih)jikadikerjakantanpanya.
13.16 DaftarKataKata
Istilah Arti Metode yang dipanggil melalui sebuah objek, yang objectmethod beroperasidenganobjekitu,yangdiacumenggunakankata kunci this dalam Java atau objek terkini dalam bahasa Indonesia. Metode dengan kata kunci static. Metode kelas tidak classmethod dipanggil melalui objekobjek dan mereka juga tidak memilikikaitandenganobjekterkini. currentobject this Objektempatdimanasebuahmetodeobjekdipanggil.Di dalammetode,objekinidiacudengankatakuncithis. Katakunciyangmengacukeobjekterkini Semua yang tidak dituliskan atau diungkapkan secara implicit langsung. Di dalam sebuah metode objek, Anda bisa mengacu ke variabel instan secara implisit (tanpa menyebutkannamaobjekyangAndamaksud). Semuayangdituliskanataudinyatakansecaralengkap.Di explicit dalam metode kelas, semua referensi yang mengacu ke variabelinstanharusdinyatakansecaraeksplisit.
295
13.17 Latihan
Latihan13.2 Ubahlahmetodekelasberikutinikedalambentukmetodeobjek. publicstaticdoubleabs(Complexc){ return Math.sqrt (c.real * c.real + c.imag * c.imag); } Latihan13.3 Ubahlahmetodeobjekberikutinikedalambentukmetodekelas. publicbooleanequals(Complexb){ return(real==b.real&&imag==b.imag); } Latihan13.4 Latihaninimerupakanlanjutandarilatihan9.3.TujuannyaadalahuntukmelatihAnda menulissintaksmetodeobjekdanmembuatAndaakrabdenganbeberapapesanerror yangrelevandenganmasalahini. a) Ubahlah metodemetode kelas yang ada dalam kelas Rational ke bentuk metode objek.Lalubuatlahperubahanseperlunyadalammetodemain. b) Buatlahbeberapakesalahan!Cobalahmemanggilmetodekelasdengancarayang sama seperti ketika Anda memanggil metode objek. Lalu lakukan hal yang sebaliknya.Cobalahmencaritahuhalhalmanayanglegaldanmanayangtidak. Selainitu, pelajarijugapesanpesanerroryangAnda dapat ketikaAnda sengaja mengacaukankeadaan. c) Pikirkanmengenaiprodankontrayangmenyelimutipenggunaanduatipemetode 296
297
14.2 KelasNode
Seperti biasa, ketika kita menulis sebuah kelas baru, kita akan memulainya dengan variabel instan. Lalu dengan satu atau dua konstruktor baru kemudian diteruskan denganpembuatanmetodetoStringagarkitabisamengujimekanismedasardalamhal pembuatandanpenyajiantipebarutersebut. publicclassNode{ intcargo; Nodenext;
298
publicNode(){ cargo=0; next=null; } publicNode(intcargo,Nodenext){ this.cargo=cargo; this.next=next; } publicStringtoString(){ returncargo+""; } } Deklarasiuntukvariabelvariabelinstansudahmengikutispesifikasiyangadasecara alami, sementara sisanya tinggal menyesuaikan dengan variabel instan. Ekspresi cargo + "" sebenarnya agakagak aneh, tapi justru inilah cara terbaik untuk mengkonversisebuahintegermenjadiString. Untukmengujiimplementasiini,kitaakanmeletakkankodesepertiinidalammain: Nodenode=newNode(1,null); System.out.println(node); Hasilnyaadalah 1 agartambahmenarik,kitamembutuhkansebuahlistyangterdiridariduaataulebih node! Nodenode1=newNode(1,null); 299
Nodenode2=newNode(2,null); Nodenode3=newNode(3,null); Kodeinimenghasilkantiganodetapikitamasihbelummemilikilistkarenanodenode tersebut belum kita hubungkan (linked). Diagram keadaannya akan tampak sebagai berikut:
Untuk menghubungkan nodenode itu, kita harus merancang kode sedemikian rupa sehingganodepertamaakanmengacukenodekedua,sementaranodekeduamengacu kenodeketiga. node1.next=node2; node2.next=node3; node3.next=null; Acuan milik node ketiga adalah null. hal ini mengindikasikan bahwa node ini merupakanakhirdarilist.Sekarangdiagramkeadaannyaakantampaksebagaiberikut:
adalahkenapa.
14.3 ListsebagaiCollection
Sesuatuyangmenyebabkanlistbermanfaatadalahkarenalistmerupakansuatuteknik untuk merangkai objekobjek yang berbeda menjadi satu entitas tunggal, biasanya diistilahkandengancollection.Dalamcontohini,nodepertamadarilistakanbertindak sebagaiacuanuntukkeseluruhanlist. Jika kita ingin melewatkan list sebagai parameter maka yang harus kita lewatkan hanyalah acuan yang mengacu ke node pertama. Sebagai contoh, metode printList menggunakansatunodesebagaiargumennya.Dimulaidaribagiankepala(head)list, metodeinimencetaksetiapnodesampaiselesai(ditandaidenganacuanyangberupa null). publicstaticvoidprintList(Nodelist){ Nodenode=list; while(node!=null){ System.out.print(node); node=node.next; } System.out.println(); } Untuk memanggil metode ini, kita hanya perlu melewatkan sebuah acuan ke node pertama: printList(node1); Didalam printList,kitamempunyaisebuahacuanyangmengarahkenodepertama 301
dalam list, tapi tidak ada variabel yang mengacu ke nodenode lainnya. Kita harus menggunakannilainextdarisetiapnodeuntukmendapatkannodeberikutnya. Diagramberikutinimenunjukkannilailistdannilaiyangdiambilolehnode:
Pergerakan untuk menelusuri sebuah list seperti ini sering disebut dengan istilah traversal. Sama seperti pola penelusuran yang telah kita lakukan terhadap elemen elemen suatuarray.Adalahhalyangbiasa/lazim untukmenggunakanvariabel loop sepertinodeuntukmengacukesetiapnodedalamlistsecaraberuntun. Hasilmetodeiniadalah 123 Jika menggunakan konvensi yang sudah ada, list sebaiknnya dicetak dalam tanda kurung(parentheses)dengankomadiantaramasingmasingelemen,misalnya(1,2,3). Untuk latihan Anda, ubahlah printList sedemikian sehingga ia bisa menghasilkan outputsepertiformatdiatas. Untuk tambahan, tulisulanglah printList menggunakan perulangan for ketimbang memakaiwhile.
14.4 ListdanRekursi
Rekursidanlistberjalanseiringseiramalaksanafavabeansdanchiantiyangnikmat. Sebagaicontoh,berikutinimerupakanalgoritmauntukmencetaksebuahlistdaribagian 302
belakang: 1. Pisahlahlistkedalamduabagian:nodepertama(sebagaikepala(head))dan sisanya(sebagaiekor(tail)). 2. Cetakekornyadaribelakang. 3. Cetakkepalanya. Tentusaja,langkahkedua,pemanggilanrekursinya,mengasumsikanbahwakitasudah mempunyaisuatucarauntukmencetaklistdaribelakang.Tapijikakitamenganggap bahwapemanggilanrekursiinibekerjadenganbaikleapoffaithbarulahkitaboleh yakinkepadadirikitasendirikalaualgoritmainitelahbekerjadenganbaikdanbenar. Yang kita butuhkan adalah base case, lalu sebuah cara untuk membuktikan bahwa untuksetiaplistyangkitagunakan,kitaakanbisakembalilagike basecase.Pilihan palingwajaruntukbasecaseadalahsebuahlistdengansatuelementunggal,tapiakan lebih baikkalau kitamau menggunakanlistkosong, yangdirepresentasikan dengan null. publicstaticvoidprintBackward(Nodelist){ if(list==null)return; Nodehead=list; Nodetail=list.next; printBackward(tail); System.out.print(head); }
Barispertamamerupakanbasecaseyangtidakmengembalikannilaiapapun.Duabaris berikutnya memecah list menjadi dua; head dan tail. Sementara dua baris terakhir digunakanuntukmencetaklistitusendiri. 303
Kita memanggil metode ini dengan cara yang sama seperti ketika kita memanggil printList: printBackward(node1); Hasilnyaadalahsebuahbackwardlist. Bisakahkitamembuktikanbahwametodeinipastiakanselalubisadihentikan?Dengan kata lain,apakahia akanselalu sampai menuju base case?Sayangnya, jawabannya adalahtidak.Adabeberapalistyangjustruakanmembuatlumpuhmetodeini.
14.5 InfiniteList
Tidakakanadayangdapatmencegahsebuahnodeuntukmengacukembalikenode sebelumnyadalamlist,tidakterkecualinodeitusendiri.Sebagaicontoh,gambarberikut inimenunjukkansebuahlistdenganduanode,satudiantaranyamengacukedirinya sendiri.
Jikakitamemanggil printBackward,metodeiniakanterusmelakukanrekursitanpa henti.Perilakusemacaminiakanmembuatkitasulitbekerjadengannya. Tapi meskipun begitu, mereka sebenarnya seringkali berguna. Contohnya, kita bisa merepresentasikan suatu bilangan dalam bentuk list yang berisi digitdigit, lalu menggunakaninfinitelistuntukmerepresentasikanbagianatauangkaangka(fraction) yangberulang(muncullebihdari1kali). Terlepas dari semua itu, sangat disayangkan karena kita tidak dapat membuktikan 304
bahwaprintListdanprintBackwardbisadihentikan.Halterbaikyagbisakitalakukan adalahmengeluarkanpernyataanbersifathipotesis(hypoteticalstatement),jikasuatu listtidakberisiperulangan,makametodeiniakanberhenti.Klaimsepertiinidisebut precondition.Klaiminimenekankanpadasatuhambatanyangterdapatdalamsalah satu parameter lalu mendeskripsikan perilaku metode tersebut jika hambatan yang dimaksudmuncul.Kitaakanmelihatcontohlainsesaatlagi.
14.6 TeoremaAmbiguitasFundamental
Adabagiandalam printBackward yangmungkinakanmembuatAndamengangkat keduaalis: Nodehead=list; Nodetail=list.next; Setelahargumenpertama, head dan list mempunyaitipedannilaiyangsama.Lalu kenapasayamembuatsatuvariabelbaru? Alasannyaadalahkarenakeduavariabeltersebutmemilikifungsiyangberbeda.Kita menganggapheadsebagaisebuahacuanyangmengacukenodetunggal,sementaratail, kitamenganggapnyasebagaiacuanyangmengacukenodepertamadalamlist.Aturan aturaninimemangbukanbagiandalamprogram;tapikeduanyaadadalambenaksang programmer. Assignment keduamembuatsebuahacuanbarukenodekeduadalamlist,tapidalam kasus ini kita menganggapnya sebagai sebuah list. Jadi, meskipun head dan tail memilikitipeyangsama,keduanyatetapmemainkanperanyangberbeda. Ambiguitassepertiinisangatbermanfaat,tapidapatmenyebabkanprogramprogram denganlistjustrusulitdibaca.Sayaseringmenggunakannamanamavariabelseperti
305
node dan list untuk mendokumentasikan bagaimana saya menggunakan sebuah variabel, dan terkadang saya juga membuat variabel tambahan agar tidak terjadi ambiguitaslagi. Sayabisamenulis printBackward tanpa head dantail,tapisayapikirhalinijustru akanmembuatnyasemakinsulituntukdibaca: publicstaticvoidprintBackward(Nodelist){ if(list==null)return; printBackward(list.next); System.out.print(list); }
Ketikakitamelihatpemanggilanduafungsi,kitaharusingatbahwa printBackward memperlakukan argumennya sebagai sebuah list sementara print memperlakukan argumennyasebagaisebuahobjektunggal. Ingatlahmengenaiteoremaambiguitasfundamental: Sebuahvariabelyangmengacukesebuahnodemungkinakanmemperlakukannode tersebutsebagaisebuahobjektunggalatausebagainodepertamadalamlist.
14.7 MetodeObjekUntukNodeNode
Anda mungkin akan heran kenapa printList dan printBackward masuk ke dalam golonganmetodekelas.Sayasudahmembuatklaimsebelumnyabahwasemuayang bisaditulissebagaimetodekelasjugabisaditulissebagaimetodeobjek;masalahnya adalahformatmanayangAndaanggaplebihjelas. Dalamkasusiniterdapatsebuahalasanbaguskenapakitasampaimenggunakanmetode objek.Adalahsuatuyanglegalmengirimkannullsebagaiargumenkemetodekelas, 306
14.8 MemodifikasiList
Satucarayangjelasjelasbisadipakaiuntukmemodifikasisebuahlistadalahdengan mengubahkargosalahsatunodeyangada.Namun,operasiyanglebihmenarikadalah dengancaramenambahkan,menghilangkan,ataumengubahurutannodenodetersebut. Sebagai contoh, kita akan menulis sebuah metode yang dapat menghilangkan node keduadalamlistlalumemberikanhasilyangberupaacuankenodeyangdihilangkan. publicstaticNoderemoveSecond(Nodelist){ Nodefirst=list; Nodesecond=list.next; //makethefirstnoderefertothethird first.next=second.next; // separate the second node from the rest of the //list second.next=null; returnsecond; }
307
Lagilagi,disinisayamenggunakanvariabeltemporeragarkodediataslebihmudah dibaca.Berikutiniadalahcaramenggunakanmetodeini. printList(node1); Noderemoved=removeSecond(node1); printList(removed); printList(node1); Hasilnyaadalah (1,2,3)theoriginallist (2)theremovednode (1,3)themodifiedlist Berikut ini adalah diagram keadaan yang menunjukkan efek yang ditimbulkan oleh operasiini.
14.9 WrappersdanHelpers
Untukbeberapaoperasilist,akansangatbergunajikakitapisahkanmetodeinimenjadi 308
dua. Sebagai contoh, untuk mencetak satu list dari belakang dalam bentuk yang konvensional,yakni(3,2,1),kitabisamenggunakanprintBackwarduntukmencetak 3, 2,tapikitamembutuhkansatumetodeterpisahuntukmencetaktandakurungdan nodepertamanya.KitaakanmenyebutnyaprintBackwardNicely. public static void printBackwardNicely { System.out.print("("); if(list!=null){ Nodehead=list; Nodetail=list.next; printBackward(tail); System.out.print(head); } System.out.println(")"); } Kembali, adalah ide yang bagus untuk memeriksa metodemetode seperti ini untuk melihatapakahmerekabenarbenarberfungsidengankondisikondisikhusussepertilist kosongatausebuahsingleton. Di bagianmanapundalamprogram,ketikakitamenggunakanmetodeini,kitaakan memanggilprintBackwardNicelylaluiaakanmemanggilprintBackwarduntukkita. Dalam kondisi seperti ini, printBackwardNicely bertindak sebagai wrapper. SementaraprintBackward,yangberadadalamprintBackwardNicely,disebutsebagai helper. (Node list)
309
14.10 KelasintList
Ada beberapa masalah serius dan penting terkait dengan cara kita dalam mengimplementasikanlist.Dalamhukumsebabakibatyangselaluberubahubah,saya akanmemperlihatkansebuahcaraalternatifuntukmengimplementasikanlistnyadahulu baru kemudian menjelaskan kepada Anda semua masalah apa yang dapat diselesaikannya. Pertamatama,kitaakanmembuatsebuahkelasbaru,IntList.Variabelinstankelasini adalahsebuahintegeryangberisipanjanglistdansebuahacuankenodepertamadalam list.ObjekobjekIntListbertindaksebagaimanipulatorlistmilikobjekobjekNode. publicclassIntList{ intlength; Nodehead; publicIntList(){ length=0; head=null; } } Satu halbagusmengenaikelasIntListadalahkarenaiadapatmemberikitatempat, secara alami, untuk meletakkan fungsi pembungkus (wrapper) seperti printBackwardNicelydimanabisamembuatsebuahmetodeobjekdalamkelasIntList. publicvoidprintBackward(){ System.out.print("("); if(head!=null){
310
Nodetail=head.next; Node.printBackward(tail); System.out.print(head); } System.out.println(")"); } Untuk membuatnya menjadi semakin membingungkan, saya menamai ulang printBackwardNicely. Nah, karena sekarang ada dua metode dengan nama printBackward:satuadadalamkelasNode(helper)sementarasatunyalagiberadadi dalam kelas IntList (wrapper). Agar wrapper bisa memanggil helper, ia harus mengidentifikasikelasnyasecaraeksplisit(Node.printBackward). Jadi,satukeuntungandarikelasIntListadalahkarenaiadapatmenyediakantempat yang bagus untuk meletakkan fungsifungsi pembungkus (wrapper). Keuntungan lainnyaadalahkarenaiadapatmemudahkankitauntukmenambahataumenghilangkan elemenpertamadalamlist.Sebagaicontoh, addFirst merupakanmetodeobjekmilik IntList;metodeinimenggunakansebuahintsebagaiargumennyalalumeletakkannya keposisipertamadalamlist. publicvoidaddFirst(inti){ Nodenode=newNode(i,head); head=node; length++; } Seperti biasa, untuk memeriksa kode seperti ini, adalah hal yang bagus untuk memikirkanbeberapakasuskhusus.Seperti,apayangterjadijikalistpadaawalnya
311
sudahdiinisialisasidalamkeadaankosong?
14.11 Invariants
Beberapa list memang sudah berada dalam keadaan yang wellformed, sementara yang lain tidak.Sebagai contoh, jikasebuah list berisi sebuah perulangan, ini akan menyebabkan rusaknya beberapa metode yang sudah kita buat. Jadi, mungkin kita menginginkanagarlistkitatidakberisiperulangansamasekali.Syaratlainnyaadalah bahwanilai length dalamobjek IntList harussamadenganjumlahnodeyangberada dalamlist. Persyaratan seperti ini disebut invariants karena, idealnya, mereka harusnya selalu bernilai true untuksemuaobjeksepanjangwaktu.Menentukan invarian untukobjek objek merupakan praktik pemrograman yang bermanfaat karena dapat memudahkan kitaketikahendakmeningkatkantingkatkebenaransuatukode,memeriksaintegritas strukturdatayangdigunakan,danmendeteksierror. Satu hal yang sering membingungkan mengenai invarian adalah bahwa mereka terkadangjustrudilanggardalamkodeprogram.Contohnya,ditengahaddFirst,setelah kita menambahkan nodenya, tapi sebelum kita menaikkan nilai length, invariannya justrudilanggar.Pelanggaransepertiinimasihbisaditerima;kenyataannya,terkadang mustahilbagikitauntukmemodifikasisebuahobjektapamelanggarsebuahinvarian meskipunituuntuksesaatsaja.Normalnya,persyaratanyangharusdisertakanadalah bahwa semua metode yang melanggar suatu invarian harus bisa mengembalikan/memperbaikinya(restore)lagi. Jikaadasesuatuyangsignifikandalamkodesehinggasuatuinvarianternyatadilanggar, adalah penting bagi komentar untuk menjelaskannya, sehingga tidak akan ada lagi operasiyangbergantungkepadainvariantersebut.
312
14.12 DaftarKataKata
Istilah list Arti Struktur data yang mengimplementasikan sebuah koleksi menggunakan sekumpulan nodenode yang saling terhubung. Suatu elemen dalam list, biasanya diimplementasikan node cargo link sebagaisebuahobjekyangberisiacuankeobjeklainyang samatipenya. Itemdatayangdikandungsebuahnode. Sebuahacuanobjekyangdimasukkankedalamobjek.
genericdatastructure Sejenisstrukturdatayangberisidatadaritipeapapun. precondition Sebuahfaktayangharusbernilai true agarsebuahmetode bisabekerjadenganbaik. Sebuahfaktayangseharusnyabernilai true untuksebuah invariant objek sepanjang waktu (kecuali mungkin ketika objek tersebutsedangdimodifikasi). Sebuah metode yang bertindak sebagai penengah antara wrappermethod sebuah metode pemanggil (caller) dan metode penolong (helper method), seringkali berupa interface yang lebih bersihketimbangmetodepenolongnya.
14.13 Latihan
Latihan14.2 MulailahdenganmengunduhfileIntList.javadarihttp://thinkapjava/code/IntList.Link iniberisidefinisidefinisimengenaiIntListdanNodedaribabini,bersamakodeyang 313
mendemonstrasikandanmengujibeberapametode.Compilelalueksekusiprogramitu. Hasilnyaakantampaksebagaiberikut: (1,2,3) (3,2,1) LatihanberikutinimemintaAndauntukmenulismetodeobjektambahanbagikelas IntList.TetapimungkinAndainginmenulisbeberapametodepenolongdalamkelas Nodesepertibiasa. SetelahAndamenulismasingmasingmetode,tambahkankodeitukedalammainlalu ujilah. Yakinlah untuk menguji beberapa kasus khusus seperti listlist kosong atau singleton. Untuksetiapmetode,identifikasilahsemuapreconditionyangdiperlukanagarsemua metodebisaberfungsidenganbenarlalutambahkankomentaryangakanbisamenjadi dokumentasiuntuknya.KomentarAndajugaharusmengindikasikanapakahmasing masingmetodemerupakankonstruktor,fungsi,ataukahmodifier. a) Tulislahmetode removeFirst yangmampumenghapusnodepertamadarisebuah list.Metodeinimampumengembalikankargoyangdimilikiolehlisttersebut. b) Tulislahmetodesetyangmenggunakansebuahindex,i,dansebuahitemdarikargo. Metodeinimampumenukarkargonodeurutankeidengankargoyangdiberikan. c) Tulislahmetodeaddyangmenggunakansebuahindex,i,dansebuahitemdarikargo. Metodeiniakanmenambahkansebuahnodebaruyangberisikargoyangdiberikan keposisii. d) Tulislah metode addLast yang menggunakan sebuah item dari kargo lalu menambahkannyakeposisibuncitdalamlist. e) TulislahmetodereverseyangbisamemodifikasiIntList,yangdapatmemutarbalik urutannodenodeyangadadidalamnya. 314
f) Tulislah metode append yang menggunakan sebuah IntList sebagai parameter. Metodeinibisamenambahkansalinandarinodenodeyangadadalamparameterlist (listyangmenjadiparameter)keposisibuncitdarilistyangsedangaktifdipakaisaat itu(currentlist). g) Tulislah metode checkLength yang mengembalikan nilai true jika panjang field yangadasamadenganjumlahnodeyangadadalamlist,dan false jikasebaliknya. Metodeinitidakbolehmenyebabkanterjadinyaexceptiondibawahkondisiapapun, daniaharusbisaberhentibahkanjikalisttersebutberisiperulangan. Latihan14.2 Satu cara untuk merepresentasikan angka yang sangat besar adalah dengan menggunakan sebuah daftar (list) berisi digitdigit, yang biasanya disimpan dalam posisiyangsudahterurut.Sebagaicontoh,angka123akandirepresentasikandenganlist (3,2,1). Tulislah sebuah metode yang membandingkan dua bilangan yang direpresentasikan sebagaiIntListdanyangbisamengembalikan1jikabilanganpertamayanglebihbesar, 1jikayangkedualahyanglebihbesar,dan0jikakeduanyasama.
315
ADT menyederhanakan tugas Anda ketika hendak menentukan sebuah algoritmajikaAndabisamengidentifikasioperasioperasiyangAndabutuhkan tanpaharusberpikirpadasaatyangbersamaanmengenaibagaimanaoperasi operasitersebutakandikerjakan.
Varianvarian ADT yang sudah populer, seperti Stack ADT dalam bab ini, seringdiimplementasikandidalampustakastandar(standardlibrary)sehingga
316
merekabisaditulissekalidanlangsungdigunakanolehbanyakprogrammer.
Ketika kita berbicara mengenai ADT, kita sering membedakan antara kode yang menggunakanADT,disebut clientcode,darikodeyangmengimplementasikanADT, disebut providercode karenakodeinimenyediakansebuahkumpulanstandaryang terdiridarilayananlayanan.
15.2 TheStackADT
Dalambabini,kitaakanmelihatsalahsatuADTyangsudahbanyakdikenal,yakni stack.Stackmerupakansuatukoleksi(collection).Iniartinya,stackadalahstrukturdata yangberisilebihdarisatuelemen.Koleksilainyangsudahkitalihatsebelumnyaantara lain;arraydanlist. Sepertiyangsudahsayasebutkan,sebuahADTdidefinisikandengansuatukumpulan yangterdiridarioperasioperasi.Stackbisamelakukanoperasioperasiberikutini: Constructor:membuatsebuahstackyangbarusekaliguskosong. Push:menambahkanitembarukedalamstack. Pop:menghapusdanmengembalikansebuahitemdaristack.Itemyangdikembalikan harusberupaitemterakhiryangditambahkan. IsEmpty:memeriksaapakahstackdalamkeadaankosong. Sebuahstackseringjugadisebutdenganlastin,firstout,ataustrukturdataLIFO, karena item terakhir yang ditambahkan akan menjadi item pertama yang akan dihilangkan.
317
15.3 ObjekStackdalamJava
Java menyediakan sebuah tipe objek bawaan yang disebut Stack yang mengimplementasikantipedataabstrakstack.Andaharusberusahauntukmembedakan keduahaliniversiADTdanversiJavadenganjelas.Sebelummenggunakankelas Stack,kitaharusmengimpornyaterlebihdahuludarijava.util. BerikutinimerupakansintaksuntukmembuatsebuahStackyangbaru: Stackstack=newStack(); padamulanya,stackyangkitabuattidakberisisatuelemenpunaliaskosong,kitabisa mengkonfirmasikeadaaninidenganmetodeisEmptyyangakanmengembalikanhasil berupanilaiboolean: System.out.println(stack.isEmpty()); Stack merupakan struktur data yang bersifat generik. Ini berarti bahwa kita bisa menambahkanitembertipeapapunkedalamnya.Meskipunbegitu,dalamimplementasi Java,kitahanyabisamenambahkantipetipeobjek.Untukcontohpertama,kitaakan menggunakan objek Node yang digunakan dalam bab sebelumnya. Mari kita mulai denganmembuatlalumencetaksebuahdaftaryangpendek(shortlist): IntListlist=newIntList(); list.addFirst(3); list.addFirst(2); list.addFirst(1); list.print(); hasilnya adalah (1, 2, 3). Untuk meletakkan sebuah objek Node ke dalam stack, gunakanmetodepush: stack.push(list.head); Perulanganberikutiniakanmenelusuridaftartersebutdanmemasukkan(push)semua 318
nodekedalamstack.
for (No de nod e= list .hea d; nod e!=nul l; nod e= node .nex t) { stack .pus h(n ode) ; }
Kitabisamengambil/menghapussebuahelemendaristackmenggunakanmetodepop. Objectobj=stack.pop(); Tipekembaliandari pop berupa Object! Initerjadikarenaimplementasistacktidak benarbenarmengetahuitipetipeobjekyangdikandungnya.Ketikakitamemasukkan objekobjekNode,merekadikonversikansecaraotomatismenjadiObject.Ketikakita mengambilobjekobjektersebutdaristack,kitaharusmengcastmerekamenjadiNode kembali. Nodenode=(Node)obj; System.out.println(node); Sayangnya,programmerjustruakanmengalamikesulitanbesaruntukmelacakjejak objekobjekdalamstackdanjugaketikahendakmengcast merekakembaliketipe yangbenarsebelummerekadiambil.JikaAndamencobauntukmengcastsebuahobjek ke dalam tipe yang salah, Anda akan mendapatkan sebuah pesan error; ClassCastException. Perulanganberikutinimerupakanidiomyangseringdipakaiuntukmengambilsemua elemendaridalamstack,laluberhentiketikastacktersebutsudahkosong: while(!stack.isEmpty()){ Nodenode=(Node)stack.pop(); System.out.print(node+""); }
319
Hasilnyaadalah 321.Dengankatalain,kitabarusajamenggunakansebuahstack untukmencetakelemenelemenyangadadalamdaftarsecaraterbalik!Perhatikan,cara inibukanlahformatstandaryangbiasadigunakanuntukmencetaksebuahdaftar,tapi denganstack,halinijustrusangatmudahdilakukan. Andaharusmembandingkankodeinidenganimplementasiyangsudahkitagunakan untukmetodeprintBackwardyangberadadalambabsebelumnya.Terdapatsemacam kaitanyangalamiahsekaligusparallelantaraversirekursifdariprintBackwarddengan algoritma stack di sini. Perbedaannya adalah karena printBackward menggunakan runtimestackuntukmelacakkeberadaannodenodeketikaiamenelusurisuatudaftar, lalu mencetak hasilnya secara terbalik dengan rekursi. Algoritma stack sebenarnya melakukan hal yang sama, hanya saja algoritma ini menggunakan objek Stack ketimbangmenggunakanruntimestack.
15.4 KelasPembungkus
Untuk setiapprimitifdalamJava,terdapatsebuahobjekbawaanyangdisebutdengan kelas pembungkus (wrapper classes). Sebagai contoh, kelas pembungkusuntuk int adalahInteger;untukdoubledisebutdenganDouble. Kelaspembungkusmenjadibermanfaatkarenabeberapafaktor:
Andabisamenginstansiasikelaspembungkuslalumembuatobjekobjekyang berisinilainilaiprimitif.Dengankatalain,Andabisamembungkussebuahnilai primitif dengan sebuah objek. Hal ini akan bermanfaat jika Anda ingin memanggilsebuahmetodeyangmembutuhkansebuahtipeobjek.
Setiap kelas pembungkus berisi nilainilai khusus (seperti nilai minimum da maximum untuk sebuah tipe), dan metodemetode yang berfungsi untuk mengkonversidarisatutipeketipelainnya. 320
15.5 MembuatKelasPembungkus
Cara yang paling cepat untuk membuat sebuah objek pembungkus adalah dengan menggunakankonstruktornyasendiri: Integeri=newInteger(17); Doubled=newDouble(3.14159); Characterc=newCharacter(b); Secarateknis,sebenarnya String bukanlahsebuahkelaspembungkuskarenatipeini tidakberhubungandengantipeprimitifmanapun,tapisintaksuntukmembuatobjek Stringadalahsamaseperticaraberikut: Strings=newString("fred"); Disisilain,belumpernahadaseorangpunyangmenggunakankonstruktoruntukobjek objekStringkarenaAndabisamendapatkanhasilyangsamadengannilaiStringyang lebihsederhana: Strings="fred";
15.6 MembuatKelasPembungkusLagi
Beberapakelaspembungkusmemiliki konstruktor keduayangmenggunakansebuah String sebagai argumennya lalu untuk mengubahnya ke bentuk yang diinginkan. Sebagaicontoh: Integeri=newInteger("17"); Doubled=newDouble("3.14159"); Prosespengubahan/konversitipeinisayangnyatidakkokoh(robust).Sebagaicontoh, jikaStringyangdigunakantidakberadadalamformatyangbenarmakaStringtersebut 321
akan menyebabkan munculnya NumberFormatException. Semua karakter non numerikdalamString,termasukspasi,akanmengakibatkangagalnyaproseskonversi. Integeri=newInteger("17.1");//WRONG!! Doubled=newDouble("3.1459");//WRONG!!
AdalahideyangbagusuntukmemeriksaformatStringyangdigunakansebelumAnda mencobauntukmengubahnya.
15.7 MengeluarkanNilaiNilai
Javamengetahuicaramencetakobjekobjekpembungkus,caratermudahadalahdengan mengambilsuatunilaiadalahcukupdenganmencetakobjektersebut: Integeri=newInteger(17); Doubled=newDouble(3.14159); System.out.println(i); System.out.println(d);
AlternatiflainyangbisaAndagunakanadalahdenganmemanfaatkanmetodetoString. MetodeinibisaAndagunakanuntukmengubahisiobjekpembungkusmenjadiString; Stringistring=i.toString(); Stringdstring=d.toString(); Akhirnya,jikaAndahanyainginmengambilnilaiprimitifdarisuatuobjek,adasebuah metodeobjekdalamtiapkelaspembungkusyangmengerjakantugasini: intiprim=i.intValue(); doubledprim=d.doubleValue(); Ada juga metodemetode yang bisa digunakan untuk mengubah objekobjek 322
15.8 MetodeMetodeBermanfaatdalamKelasPembungkus
Seperti yang telah saya sebutkan, kelaskelas pembungkus berisi metodemetode bermanfaat yang berkaitan dengan masingmasing tipe. Sebagai contoh, kelas Character berisimetodemetode,dalamjumlahyangmelimpah,yangbisadigunakan untukmengubahkarakterkebentukuppercasedanlowercase.Jugauntukmemeriksa apakahsebuahkaraktermerupakanangka,huruf,ataukahsimbol. KelasStringjugaberisimetodemetodeuntukmelakukanpengubahankebentukupper dan lower case. Meskipun demikian, Anda harus tetap ingat bahwa mereka adalah fungsi,bukanmodifier(lihatsubbab7.9). Untuk contoh tambahan, kelas Integer juga berisi metodemetode untuk menginterpretasikandanmencetakintegerintegerkebentukyangberbedabeda.Jika Anda mempunyai sebuah String yang berisi angka dalam basis 6, Anda bisa mengubahnyakebasis10menggunakanparseInt. Stringbase6="12345"; intbase10=Integer.parseInt(base6,6); System.out.println(base10);
323
15.9 EkspresiPostfix
Dalam banyak bahasa pemrograman, ekspresiekspresi matematika ditulis dengan bantuanoperatoryangdiletakkandiantaraduaoperan,sepertidalam 1+2.format seperti ini disebut infix. Format alternatif yang digunakan oleh beberapa kalkulator adalahpostfix.Dalampostfix,operatornyamengikutioperanoperannya,misalnya12 +. Alasan yang membuat postfix terkadang berguna adalah bahwa terdapat semacam kecenderunganalamiahuntukmengevaluasisuatupostfixmenggunakansebuahstack.
Dimulai dari depan/awal sebuah ekspresi, ambil satu term (operator atau operan)dalamsatuwaktu.
Ketika kita sudah sampai ke ujung/akhir sebuah ekspresi, harusnya sudah terdapat sebuah operan yang tertinggal dalam stack. Operan itulah yang menjadihasilnya.
Sebagailatihan,gunakanalgoritmainiuntukmengerjakanekspresi12+3*. Latihan ini menunjukkan salah satu kelebihan postfix: kita tidak perlu lagi menggunakantandakurunguntukmengatururutansuatuoperasi.Untukmendapatkan hasilyangsamadalaminfix.Kitamungkinharusmenulis(1+2)*3.Sebagailatihan, tulislahekspresipostfixyangekuivalendengan1+2*3?
324
15.10 Parsing
Untukmengimplementasikanalgoritmayangadadibabsebelumnya,kitaharusbisa menelusurisuatustringlalumembaginyakedalamduakelompokyaitu;operandan operator.Prosesinimerupakansebuahcontoh parsing (penguraian),laluhasilnya yangberupastringindividualdisebuttokens. Java menyediakan sebuah kelas bawaan yang disebut StringTokenizer yang bisa menguraikanstringlalumemecahnyamenjaditokentoken.Untukmenggunakankelas ini,Andaharusmengimpornyadarijava.util. Dalambentuknyayangpalingsederhana, StringTokenizer menggunakanspasispasi untukmenandaibatasantaratiaptoken.Sebuahkarakteryangmenandaisuatupembatas disebutdelimiter. Kita bisa membuat StringTokenizer dengan cara yang sudah sering kita gunakan, denganmelewatkansebuahargumenberupastringyangakankitauraikan. StringTokenizer fourtokens."); Perulangan berikut ini merupakan idiom standar untuk mengambil tokentoken dari StringTokenizer. while(st.hasMoreTokens()){ System.out.println(st.nextToken()); } Hasilnyaadalah: Here are st = new StringTokenizer ("Here are
325
22+33*","+*/");
ArgumenkeduaadalahsebuahStringyangberisisemuakarakteryangakandigunakan sebagaidelimiter.Hasilnyaadalah: 11 22 33 Cara ini memang bekerja dengan baik untuk mengambil semua operannya tapi sayangnyakitajugaakankehilanganoperatoroperatornya.Untungnya,masihadasatu opsilagidariStringTokenizer. StringTokenizer st = new StringTokenizer ("11
* Inihanyalahtokentokenyangakankitagunakanuntukmengevaluasiekspresiekspresi ini.
15.11 MengimplementasikanADT
SalahsatutujuandasardariADTadalahuntukmemisahkankebutuhansangpenyedia (provider),sipenuliskodeyangmengimplementasikanADT,dansangklien(client), orangyangmenggunakanADT.Sangpenyediahanyaperlumengkhawatirkanmasalah benartidaknyapengimplementasianapakahsudahsesuaidenganketentuandariADT ataukahbelumbukanpadabagaimanakodenyaakandigunakan. Sebaliknya, sang klien mengasumsikan bahwa implementasi yang diterapkan untuk suatuADTadalahsudahbenarsehinggatidakperlulagimengkhawatirkandetailnya. Ketika Anda sedang menggunakan salah satu kelas bawaan Java, Anda memiliki kemewahanuntukberpikirsecaraeksklusifsebagaiseorangklien. Ketika Anda mengimplentasikan sebuah ADT, di sisi yang lain, Anda juga harus menuliskodedariklienuntukmengujinya.Untukkasusini,Andasebaiknyaberhati hatiterhadapaturanyangakanAndaterapkanuntukinstanyangakanAndagunakan. Di bagian selanjutnya, kita akan menukar gears dan melihat salah satu cara untuk mengimplementasikan stack ADT yakni dengan bantuan array. Sekarang mulailah berpikirlaksanaseorangprovider.
15.12 ImplementasiArrayuntukStackADT
Variabelvariabel instan untuk mengimplementasikan kasus ini adalah sebuah array yangberisisekumpulanObject.Arrayinisendirinantinyaakanberisiitemitemyang beradadalamstackdansebuahindeks,berupainteger,yangakanmemberitahukita 327
tentangsisaspasiyangadadalamarray.Padamulanya,arrayinikosong.Sementara indeksnyadisetdengannilai0. Untukmenambahkansebuahelemenkedalamstack(push),kitaakanmenyalinacuan yang mengacu kepadanya ke dalam stack lalu menaikkan indeksnya satu per satu (increment).Untukmengambilsebuahelemen(pop),kitaharusmendecrementindeks terlebihdahulubarumengeluarkannya. Berikutinidefinisikelasnya: publicclassStack{ Object[]array; intindex; publicStack(){ this.array=newObject[128]; this.index=0; } } Sepertibiasa,jikakitasudahmenuliskanvariabelvariabelinstannya,makaotomatis kitajugaakanmenuliskankonstruktordidalamnya.Untuksekarang,jumlahelemen yangakankitagunakanadalah128item.Nanti,kitaakanmempelajarialternatiflain yanglebihbaikuntukmenanganikasussemacamini. Memeriksakosongtidaknyastackbisadilakukandengancarayangsederhana. publicbooleanisEmpty(){ returnindex==0; } Meskipunsederhana,pentinguntukdiingatbahwajumlahelemendidalamstacktidak sama dengan ukuran array. Pada awalnya, ukuran array adalah 128 tetapi jumlah 328
elemennyasamadengan0. Implementasiuntukpushdanpopbisadilakukandengancarasepertiberikut. publicvoidpush(Objectitem){ array[index]=item; index++; } publicObjectpop(){ index; returnarray[index]; } Untukmengujikeduametodeini,kitabisamemanfaatkankodeklienyangsebelumnya kita gunakan untuk menguji Stack bawaan. Kemudian, ketimbang menggunakan impelementasistackmilik java.util,programkitajustruakanmemakaiimplementasi yangtelahkitatulissebelumnya. Jikasegalasesuatunyaberjalansesuaidenganrencana,programharusnyalangsungbisa berfungsitanpaperlupenambahandisanasini.Daningat,salahsatunilailebihketika menggunakanADTadalahkarenaAndabisamengubahsuatuimplementasitanpaharus mengubahkodekliennya.
15.13 MengubahUkuranArray
Sebuah kelemahan dari penggunaan implementasi seperti ini adalah karena ia telah membuatalokasiarraysecarakakuuntuksetiapStackyangakandibuat.Jikapengguna memasukkanlebihdari128itemkedalamstack,makaprogramakanmengeluarkan eksepsiyangberbunyiArrayIndexOutOfBounds.
329
Alternatifuntukkasusiniadalahdenganmengizinkankodeklienuntukmenentukan ukuranarraytersebut.Carainimemangmenyelesaikanmasalahnya,tapihalinihanya bisadilakukandengansyaratbahwasangklieharustahuterlebihdahulujumlahitem yangdibutuhkan.Dansayangnya,halinisepertinyatidakbisaterjadisetiapsaat. Berikutiniversipushyangtelahdiperbaiki: publicvoidpush(Objectitem){ if(full())resize(); //disinikitabisamembuktikanbahwa //indeks<array.length array[index]=item; index++; } Sebelummeletakkanitembarukedalamarray,kitaakanmemeriksaapakaharraysudah penuh? Jika ya, kita panggil metode resize. Setelah pernyataan if, kita akan tahu apakah; 1. memangsudahterdapatruangyangtersisadalamarray,atau 2. arraysudahdiubahukurannyasehinggaterdapatruangyangtersisadidalamnya. Jikafulldanresizesudahbenar,makaselanjutnyakitabisamembuktikanbahwaindex <array.length,danolehkarenaitupernyataanberikutnyatidakakanmenyebabkan eksepsilagi. Sekarang,yangharuskitalakukaadalahmengimplementasikanfulldanresize. privatebooleanfull(){ returnindex==array.length; } 330
privatevoidresize(){ Object[] newArray = new Object[array.length 2]; // kita asumsikan bahwa array yang lama sudah penuh for(inti=0;i<array.length;i++){ newArray[i]=array[i]; } array=newArray; } *
Keduametodedideklarasikansecaraprivate,iniberartikeduanyatidakbisadipanggil darikelasyanglain.Bisanyahanyadarikelasini.Halsemacaminibisaditerimadengan alasankarenamemangtidakalasanbagikodeklienuntukmenggunakanfungsiini,atau bahkan hanya sekedar ingin menggunakannya, karena metode ini memang sengaja dibuatuntukmenjadipembatasantarakodeproviderdengankodeklien. Implementasiuntukmetodefullsangatsederhana;metodeinihanyamemeriksaapakah indekstelahmelampauiukuranindeksyangtelahditetapkansebelumnya. Pun begitudenganimplementasi untukmetode resize,hanyadengan asumsibahwa arrayyanglamasudahpenuh.Dengankatalain,asumsitersebutmerupakanprasayarat untuk metodeini.Sangatmudahbagikitauntukmelihatbahwaprasyaratinisudah memenuhi syarat karena satusatunya cara untuk memanggil resize adalah jika full bernilaitrue.Nilaiinihanyabisaterjadijikaidex==array.length. Di akhir metode resize, kita mengganti array yang lama dengan array yang baru
331
(menyebabkan array lama berstatus garbage collected). array.length yang baru berukuranduakalilebihbesarketimbang arrayyanglama,sementara index belum berubahsehinggapernyataanindex<array.lengthpastilahbernilaibenar.Faktafakta diatasmerupakanpostconditionuntukresize;sesuatuyangharusbernilaitrueketika metodetelahselesaidieksekusi(selamaprasyaratnyajugasudahdipenuhi). Prasyarat, postcondition, dan invariant merupakan tools yang sangat berguna untuk menganalisa program sekaligus menunjukkan tingkat ketepatan (correctness) yang terkandung di dalamnya. Dalam contoh ini saya telah menunjukkan sebuah teknik pemrograman yang memfasilitasi analisis program sekaligus sebuah teknik pendokumentasianyangbisamembantupeningkatanmutukeakuratannya.
15.14 DaftarKataKata
Istilah ADT Arti Sebuah tipe data (umumnya merupakan kumpulan dari objek)yangdidefinisikandengansekumpulanoperasi,tapi yangbisadiimplementasikandenganberbagaicara. client provider Sebuah program yang menggunakan ADT (atau sebutan untukorangyangmenulisprogramnya). KodeyangmengimplmentasikansuatuADT(atausebutan untukorangyangmenulisnya). Salah satu kelas dalam Java,seperti Double dan Integer wrapperclasses yang memungkinkan objekobjek mengandung tipetipe primitif, dan metodemetode yang beroperasi di atas primitif. private KatakuncidalamJavayangmengindikasikanbahwasebuah metode atau variabel instan tidak bisa diakses dari luar 332
definisikelasnyasendiri. Suatu cara dalam menulis ekspresiekspresi matematika infix dengan posisi operator yang berada di antara operan operannya. Suatu cara dalam menulis ekspresiekspresi matematika postfix dengan posisi operator yang berada di belakang operan operannya. Membacasebuahstringyangterdiridarikarakterkarakter parse atautokentokenuntukmenganalisastrukturtatabahasanya (grammaticalstructure). Sekumpulan karakterkarakter yang diperlakukan sebagai token sebuahunituntuktujuanparsing,sepertikatalaiknyadalam bahasaalamiah. delimiter predicate Sebuahkarakteryangdigunakanuntukmemisahkantoken token,sepertitandabacalaiknyadalambahasaalamiah. Sebuahpernyataanmatematisyangbisabernilaibenaratau salah. Sebuahpredikatyangharusbernilaibenardiakhirsebuah postcondition metode (dengan catatan bahwa prasyaratnya juga bernilai benardiawalmetode).
15.15 Latihan
Latihan15.1 Tulislahmetodereverseyangmengambilsebuaharrayberisiinteger,menelusuriarray itu,memasukkanitemitemkedalamstack,lalumengambilitemitemitudaristack,
333
meletakkan kembali ke dalam array dalam posisi yang terbalik dari keadaan sebelumnya. Tujuan latihan ini adalah untuk mempraktikkan mekanisme pembuatan objekobjek pembungkus,memasukkandanmengeluarkanobjekobjek,danmengtypecast objek objekgenerikkebentukyanglebihspesifik. Latihan15.2 Latihan ini berdasarkan solusi dari latihan 14.1. mulailah dengan membuat salinan impelemntasiAndadarimetodeIntListyangdisebutLinkedList. a) Ubahlahimplementasilinkedlistkedalamsebuahlistyanggenerikdenganmembuat kargo untuk sebuah Object ketimbang untuk sebuah integer. Modifikasilah kode pengujinyasesuaidengankondisisekaranglalujalankanprogramnya. b) Tulislahsebuahmetode LinkedList dengannama split yangmenggunakansebuah String,memecahnyamenjadikatakata(menggunakanspasidebagaidelimiter),lalu mengembalikansebuahlistyangberisi String,dengansatukatauntuksetiapnode dalamlist tersebut.Implementasi Anda haruslahefisien, ini berarti bahwawaktu yangdihabiskanharussesuaidenganjumlahkatayangadadalamstring. c) TulislahsebuahmetodeLinkedListdengannamajoinyangmengembalikansebuah StringyangberisirepresentasiStringdarisetiapobjekyangberadadalamlist,terurut sesuaidenganurutankemunculannya,dengansebuahspasiyangmenjadipemisah. d) TulislahmetodetoStringuntukLinkedList. Latihan15.3 TulislahsebuahimplementasidariStackADTmenggunakanimplementasiLinkedList milikAndasendirisebagaistrukturdatautamanya.Adaduapendekatanumumuntuk kasus ini: stack itu kemungkinan akan berisi sebuah LinkedList sebagai sebuah variabel instan, atau kelas Stack mungkin akan memperluas kelas LinkedList itu 334
sendiri.PilihlahyangkedengarannyalebihbaikuntukAnda,atau,jikaAndamemang benarbenar seorang yang berambisi, impelementasikan saja keduanya lalu buatlah perbandinganantarakeduanya. Latihan15.4 TulislahprogramBalance.javayangbisamembacasebuahfiledanmemeriksabahwa tandakurung,(),dankurungkotak,[],dankurungkurawal,{},telah ditulisdengan seimbangdandiletakkanditempatyangbenar. Petunjuk: LihatbagianCuntukkodeyangmampumembacabarisbarisdalamsuatu file. Latihan15.4 Tulislahmetode evalPostfix yangmenggunakansebuahStringberisiekspresipostfix dan mampu mengembalikan nilai bertipe double yang mengandung hasil perhitungannya.AndabisamenggunakanStringTokenizeruntukmenguraikanString dansebuahStackberisiDoubleuntukmengevaluasiekspresitersebut.Langkahlangkah berikutiniadalahsaransayauntukpengembanganprogrammilikAnda. a) Tulislah sebuah program yang bisa meminta user untuk memasukkan string sekaligus mencetaknya, berulangulang, sampai si pengguna mengetikkan kata quit.Lihat bagian Cuntukinformasimengenaicaramemasukkan datamelalui keyboard.Andabisamelihatkodeberikutinisebagaipermulaan: public static void inputLoop () throws IOException { BufferedReaderstdin= new BufferedReader(new while(true){ System.out.print("=>");//Cetakhasilmasukan 335 InputStreamReader (System.in));
Strings=stdin.readLine();//ambilmasukan if(s==null)break; //periksaapakahssamadengan"quit" //cetaks } } b) IdentifikasikanhelpermethodsyangmenurutAndabisadimanfaatkan,lalutulisdan debug mereka dalam lingkungan yang terisolir. Saran: isOperator, isOperand, parseExpression,performOperation. c) Kitatahubahwakitainginmenambahkannilaiintkedalamstacklalumengambilnya kembali, dengan kata lain, kita akan membutuhkan sebuah kelas pembungkus (wrapper classes). Pastikan Anda tahu bagaimana cara melakukannya lalu ujilah operasioperasitersebutdalamlingkunganyangterisolir.Mungkinmembuatmereka menjadihelpermethods. d) Tulislah versi evaluate yang hanya menangani satu jenis operator saja (seperti penjumlahan).Ujilahdalamlingkunganyangterisolir. e) HubungkanevaluatorAndadenganperulanganinput/outputAndasendiri. f) Tambahkanoperasioperasilainnya. g) Ketika Anda tahu bahwa kode ini bekerja, Anda mungkin ingin mengevaluasi struktur rancangannya.BagaimanacaraAndamembagikodeinikedalamkelas kelas?Variabelinstanapayangharusdimilikiolehkelaskelastersebut?Parameter parameterapayangharusdilewatkan? h) AgarrancanganAndatambahelegan,AndajugaharusbisamembuatkodeAnda bersifat bulletproof, maksudnya adalah agar metode ini tidak menyebabkan terjadinyaeksepsidibawahkondisiapapun,bahkanketikasipenggunamengetikkan sesuatuyanganehmisalnya. 336
Bab16
AntriandanAntrianPrioritas
Bab ini akan menyajikan dua ADT sekaligus: antrian dan antrian prioritas. Dalam kehidupanseharihari,sesuatuyangdisebutdenganantrianadalahsederetanpelanggan yang menunggu untuk suatu pelayanan tertentu. Dalam banyak kasus, pelanggan pertama yang berada dalam barisan biasanya akan dilayani terlebih dahulu. Tetapi tunggudulu,karenaternyatatidaksemuakasussertamertasepertiitu.Sebagaicontoh, dibandara,calonpenumpangyangpesawatnyaakanterbangsesaatlagiakanlangsung ditaruhdipertengahanantrian.Begitujugadisupermarket,seorangpelangganyang baikhatibiasanyamendahulukanpelangganlainyangbelanjaannyalebihsedikit. Aturan untuk menentukan siapa yang harus dilayani berikutnya disebut queueing discipline(disiplinantrian).AturanyangpalingsederhanaadalahFIFO,atauFirstIn FirstOut.Aturanyangpalingumumdigunakandisebut priorityqueueing,disini masingmasing pelanggan akan diberi tingkat prioritas, pelanggan yang memiliki prioritaspalingtinggiakandidahulukan,tanpamelihatkapansipelangganitudatang. Alasan yang membuat saya menyebutnya sebagai aturan yang paling umum adalah karenaprioritasitusendiribisaberdasarkanpadaapapunyangmemungkinkan:kapan sebuah penerbangan akan dilaksanakan, berapa banyak barang yang dimiliki oleh pelanggan,atauseberapa penting sipelanggantersebutjikadibandingkanpelanggan lainnya.Tapitentu,tidaksemuaaturanantrianbersifatadil,tohbukankahkeadilanitu sendirisejatinyaberadadalampersepsimasingmasingindividu. ADTAntrian(TheQueueADT)danADTAntrianPrioritas(ThePriorityQueueADT)
337
mempunyaisekumpulanoperasidanantarmukayangsama.Perbedaannyaterletakdi dalam semantik operasioperasinya: satu Antrian menggunakan kebijakan FIFO, sementaraAntrianPrioritas(sepertinamanya)menggunakankebijakanpemrioritasan dalamantrian. LaiknyasebagianbesarADT,adabeberapacarauntukmengimplementasikanantrian. Karenaantriansendirimerupakankumpulanitem,kitabisamenggunakanmekanisme dasarmanapununtukmenyimpankoleksikoleksitersebut,termasukarraydanlist.Di sinikitaakanmemilihteknikyangunjukkerjanyapalingbagusberapalamawaktu yangdibutuhkannyauntukmelaksanakanoperasioperasiyangkitainginkandantentu sajadalamhalkemudahanpenggunaannya.
16.1 ADTAntrian
ADTantrianakandidefinisikanolehoperasioperasiberikutini: constructor:membuatsatuantrianbaruyangkosong. add:menambahkansatuitembarukedalamantrian. remove: menghapus dan mengembalikan satu item dari antrian. Item yang dikem balikanpertamakaliadalahitemyangpertamakaliditambahkan. isEmpty:memeriksaapakahsuatuantriandalamkeadaankosongataukahtidak. Berikutiniadalahimplementasidariantriansecaraumum,berdasarkankelasbawaan java.util.LinkedList: publicclassQueue{ privateLinkedListlist; publicQueue(){ list=newLinkedList(); } 338
publicbooleanisEmpty(){ returnlist.isEmpty(); } publicvoidadd(Objectobj){ list.addLast(obj); } publicObjectremove(){ returnlist.removeFirst(); } } Satuobjekberisisatuvariabelinstan,yaknilistyangmengimplementasikannya.Untuk metodemetodelainnya,yangharuskitalakukanhanyalahmemanggilsalahsatumetode darikelasLinkedList. Kitabisamenulisimplementasiyangsamasedikitlebihjelasdenganmemanfaatkan fiturinheritance: publicclassQueueextendsLinkedList{ publicObjectremove(){ returnremoveFirst(); } }
danadd.Kitajugamewarisiremove,tetapisayangversiremoveyangkitadapatdari kelas LinkedList tidak melakukan apa yang kita maksudkan; metode ini justru menghapus elemen terakhir dalam list (daftar), bukan yang pertama. Kita akan mengatasinyadenganmembuatremoveversibaruyangakanmengoverrideversiyang kitawarisi. Pilihan yang akan kita ambil bergantung pada beberapa faktor. Pewarisan memang dapatmenyebabkansuatuimplementasimenjadilebihjelas,selamamasihadametode metodedalamkelasindukyangbisadimanfaatkan.Tetapi,fiturinijugabisamembuat suatuimplementasijustrulebihsulituntukdibacadandidebug.Haliniterjadikarena metodemetodeuntukkelasyangbarutersebuttidakberadaditempatyangsama.Selain itu, fitur ini juga bisa menyebabkan munculnya perilaku yang mungkin tidak Anda harapkan.Initerjadikarenakelasyangbaruakanmewarisi semua metodedarikelas induk,tidakhanyayangAndabutuhkan.Keadaansepertiiniakanmengakibatkankelas Queue versi kedua juga memiliki metodemetode seperti removeLast dan clear. MeskipunkeduanyabukanmerupakanbagiandariADTQueue.Implementasipertama lebihaman;denganmendeklarasikkansatuvariabelinstanyangbersifat private,kita bisa mencegah klien yang ingin memanggil metodemetode yang berada dalam LinkedList.
16.2 Veneer
Denganmenggunakan sebuah LinkedList untukmengimplementasikansatuAntrian, kitabisamengambilmanfaatdarikodeyangsudahada;kodeyangbarusajakitatulis hanya menerjemahkan metodemetode LinkedList ke dalam metodemetode Queue. Implementasisepertiinidisebut veneer (kayupelapisnantipis).Dalamkehidupandi dunianyata,veneeradalahsebuahlapisantipisyangterbuatdarikayuberkualitasbaik 340
yangdigunakandalampembuatanmebeluntukmelapiskayuberkualitaskurangbaikdi bawahnya. Ilmuwan komputer menggunakan metafora ini untuk mendeskripsikan sebuah kode kecil yang menyembunyikan detail suatu implementasi sekaligus menyediakanantarmukayanglebihsederhanadanterstandardisasi. Contoh kasus tentang Antrian akan mendemonstrasikan salah satu hal menarik mengenaiveneer,yaknikemudahandalamimplementasi,dansalahsatubahayaketika menggunakanveneeradalahkarenaperformacehazard! Normalnya,ketikakitamemanggilsebuahmetode,sebenarnyapadasaatitukitatidak terlalupedulimengenaidetailimplementasinya.Tapiadasatudetailyangmungkin inginkitaketahuikarakterunjukkerjadarisuatumetode.Berapalamawaktuyang diperlukanolehmetode,sebagaisebuahfungsidariangkaitemitemyangberadadalam list(daftar)? Untukmenjawabpertanyaandiatas,kitaharusmengetahuilebihbanyakhalmengenai implementasi. Jika kita mengasumsikan bahwa LinkedList benarbenar di implementasikan sebagai sebuah linked list (daftar yang saling terkait), maka im plementasidarimetoderemoveFirstmungkinakankelihatansepertiini: publicObjectremoveFirst(){ Objectresult=head; if(head!=null){ head=head.next; } returnresult.cargo; } Kita mengasumsikanbahwa head mengacukenodepertama dalamlist,danbahwa setiapnodenyaberisikargosertasebuahacuanyangmengarahkenodeberikutnya 341
dalamlist. Tidakadapemanggilanperulanganataufungsidisini.Akibatnya,runtimemetodeini hampir selalu sama setiap waktu. Metode seperti ini disebut dengan constant time operation.Dalamrealita,metodeinimungkinakanterlihatlebihcepatketikalistsedang kosong.Haliniterjadikarenametodeakanmelompatibagianbadan(body)daribagian persyaratan(conditional),tapiperbedaannyatidakterlalusignifikan. Unjuk kerja addLast sangat berbeda. Berikut ini adalah sebuah implementasi yang bersifathipotesis: publicvoidaddLast(Objectobj){ //specialcase:listkosong if(head==null){ head=newNode(obj,null); return; } Nodelast; for (last = head; last.next != null; last = las t.next){ terakhir } last.next=newNode(obj,null); } Syaratpertamamenanganikasuskhusus,yaknipenambahansebuahnodebarukedalam listkosong.Dalamkasusini,lagilagi,runtimetidakbergantungkepadapanjanglist. Meskipun begitu, dalam kasus yang lebih umum, kita harus menelusuri list untuk 342 // telusuri list untuK menemukan node
16.3 LinkedQueue
KitamenginginkansebuahimplementasidariADTAntrianyangbisamelakukansemua operasidalamwaktuyangkonstan.Salahsatucarauntukmenyelesaikanmasalahini adalahdenganmengimplementasikanlinkedqueue.Carainibisadibilangsamadengan linkedlistkarenaiaterdiridariobjekobjek Node yangsalingterhubung,mulaidari yangberjumlah0(tanpa Node)ataulebihdariitu.Perbedaannyaadalahbahwasuatu antrianmemeliharaacuanyangberasaldarinodepertamadanterakhir,sepertitampak dalamgambar.
343
} publicbooleanisEmpty(){ returnfirst==null; } }
Sampaisejauhini,tampaknyaimplementasiinimasihbiasabiasasaja.Didalamantrian yangkosong,baikfirstmaupunlastdiisidengannull.Untukmemeriksaapakahsuatu listsedangkosongataukahtidak,kitahanyaperlumemeriksasalahsatudiantaranya. Implementasimetode add tampaknyalebihrumitkarenakitaharusberurusandengan beberapakasuskhusus. publicvoidadd(Objectobj){ Nodenode=newNode(obj,null); if(last!=null){ last.next=node; } last=node; if(first==null){ first=last; } }
publicObjectremove(){ Noderesult=first; if(first!=null){ first=first.next; } if(first==null){ last=null; } returnresult; } Syarat pertama memeriksa apakah ada node di dalam antrian. Jika ya, kita harus menyalinnodenextkefirst.Syaratkeduaterkaitdengankasuskhususbahwalistpada saatyangbersamaansedangkosong,dalamhalinikitaharusmembuat last menjadi null. Untuk latihan,buatlahdiagramdiagramyangmenunjukkanoperasioperasiini,baik dalam kasus normal maupun kasus khusus, dan yakinkan diri Anda sendiri bahwa diagramdiagramtersebutmemangbenaradanya. Jelassekali,implementasiinitentulebihrumitketimbangimplementasiveneer,dan lebih sulit lagi untuk membuktikan bahwa implementasi ini memang benar. Keuntungannyaadalahkarenakitatelahberhasilmencapaitujuanyangkitainginkan: adddanremoveadalahmetodeyangbersifatconstanttimeoperation.
16.4 CircularBuffer
Implementasiumumlainnyadariantrianadalah circularbuffer.Buffermerupakan nama umum untuk menyebutkan sebuah lokasi penyimpanan yang sifatnya
345
sementara/temporer, meskipun ia juga sering digunakan untuk menyebutkan suatu array, seperti yang terjadi dalam kasus ini. Sekarang Anda tentu akan lebih paham denganapayangdimaksuddengankatacirculardisini. Implementasi dari circular buffer sama dengan implementasi array untuk stack di subbab15.12.Itemitemantriandisimpandidalamsebuaharray,dankitamenggunakan indeksuntukmengetahuiposisikitadidalamarray.Dalamimplementasistack,ada sebuahindekstunggalyangmenunjukkeruang(space)berikutnyayangmasihkosong. Dalamimplementasiantrian,terdapatduaindeks:firstmenunjukkeruangdalamarray yang berisi pelanggan pertama dalam barisan sementara next menunjuk ke ruang berikutnyayangmasihkosong. Gambar berikut ini menunjukkan sebuah queue dengan dua item (direpresentasikan dengantitiktitik).
Adaduacarauntukmemikirkanvariabelvariabeluntuk first dan last.Secaraliteral, keduanyabertipeinteger,dannilaimerekaditunjukkandalamkotakdisebelahkanan. Walaupunbegitu,secaraabstrak,merekamerupakanindeksdarisebuaharray.Oleh karenaitulah,merekaseringdigambarkansebagaisebuahanakpanahyangmenunjuk kelokasidalamarray.Representasianakpanahsebenarnyasangatbagus,tapiAnda harusingatbahwaindeksindekstersebutbukanlahacuan;merekahanyalahinteger. Berikutinimerupakanimplementasiarraydarisebuahantrianyangbelumlengkap: publicclassQueue{ publicObject[]array; publicintfirst,next; publicQueue(){ array=newObject[128]; first=0; 346
next=0; } publicbooleanisEmpty(){ returnfirst==next; } Variabelvariabelinstandankonstruktornyatampaknormaldanbiasabiasasaja,tapi kita lagilagi menjumpai masalah ketika dihadapkan dengan ukuran yang harus digunakanuntukarray. Nantinya kita akan menyelesaikan masalah ini, sebagaimana yang telah kita lakkan denganstack,dengancaramengubahukuranarraynyaketikaarraytersebutsudahterisi penuh. Implementasi isEmpty terkesan agak mengejutkan. Anda mungkin harus berpikir bahwa first == 0 akan mengindikasikan sebuah antrian kosong, tapi itu menge yampingkan fakta bahwa kepala antrian tidaklah harus berada di depan array. Se baliknya,kitatahubahwaantriandikatakankosongjika head samadengan next,di manadalamkasusiniberartisudahtidakadalagiitemitemyangtersisa.Sekalisaja kitamelihatimplementasiadddanremove,kondisitersebutakanlebihmasukakal. publicvoidadd(Objectitem){ array[next]=item; next++; } publicObjectremove(){ Objectresult=array[first]; first++; returnresult; } 347
Adalahselalubenarbahwanextmenunjukkeruangyangmasihkosong.Jikafirsttelah melebihinextdanmenunjukkeruangyangsama,makafirstsedangmengacukelokasi yangkosong.Sayamemberitandakutippadakatakosongkarenaadakemungkinan bahwa lokasi yang ditunjuk oleh first sebenarnya memiliki suatu nilai (kita tidak melakukanapapununtukmemastikanapakahlokasiyangkosongberisi null);disisi lain,karenakitasudahmengetahuikalauantrianitumemangkosong;kitatidakakan pernah membaca lokasi ini, jadi kita bisa menganggapnya, secara abstrak, sebagai sesuatuyangkosong. Latihan16.1 Modifikasilah remove sehinggaiabisamengembalikan null jikasuatuantriansedang kosong. Masalahberikutnyadariimplementasiiniadalahkarenaiaakanmenghabiskanbanyak ruang.Ketikakitamenambahkansebuahitem,kitajugamenaikkannilainextdanketika 348
kita kita menghapus sebuah item kita menaikkan first, tapi sayangnya kita tidak menurunkannilaikeduanya.Apayangakanterjadijikakitasudahsampaidiujung array? Gambar berikut ini menunjukkan keadaan antrian setelah kita menambahkan empat itemlagi:
arraynya sekarang telah penuh. Tidak ada lagi ruang kosong berikutnya. Jadi sekarangnexttidakbisamenunjukkemanamanalagi.Satukemungkinanadalahkita bisa mengubah ukuran array, seperti yang telah kita lakukan dengan impelementasi untuk stack.Tapidikasus itu,arraynyaakanterusmembesartanpapedulidengan berapabanyakjumlahitemyangsedangberadadidalamantrian.Solusiyanglebihbaik adalah dengan melakukan wrap around (baca: putaran) ke awal array lalu menggunakankembaliruangruangyangmasihadadisana.wraparoundsepertiini adalahalasankenapaimplementasiinidisebutdengancircularbuffer. Salah satu cara untuk memutar indeks adalah dengan menambahkan sebuah kasus khususdimanapunkitamenaikkannilaisebuahindeks: next++; if(next==array.length)next=0; Alternatifyanglebihcantikadalahdenganmenggunakanoperatormodulus: next=(next+1)%array.length; 349
Sampai di sini kita masih memiliki satu masalah terakhir yang harus diselesaikan. Bagaimana kita bisa tahu kalau antrian benarbenar sudah penuh, maksudnya; kita sudah tidakbisalagimenambahkanitemlainnya?Gambarberikutinimenunjukkan tampilanantrianketikasedangberstatuspenuh.
Masihtersisasaturuangkosongdidalamarray,tapiantrianitusudahpenuhkarenajika kita menambahkan item lainnya, maka kita harus menaikkan next sedemikian rupa sehingga next == first, dan dalam kasus ini, antrian akan kelihatan sedang berada dalamstatuskosong! Untukmenghindarihalkondisisepertidiatas,kitaakanmengorbankansaturuagdalam array.Jadibagaimanakitabisabilangkalauantrianitusudahpenuh? if((next+1)%array.length==first) Danapayangharuskitalakukanjikaarraynyapenuh?Dalamkasusini,mengubah ukuranarraymungkinadalahsatusatunyacara. Latihan16.2 Tulislah sebuah impelementasi antrian menggunakan circular buffer yang bisa mengubahukurannyasendiriketikasedangperlu.
350
16.5 PriorityQueue
ADT AntrianPrioritasmempunyaiantarmukayangsamasepertiADTAntrian,tapi semantiknyaberbeda.Antarmukanyaadalahsebagaiberikut: constructor:membuatsebuahantrianyangbarusekaliguskosong. Add:menambahkansebuahitembarukedalamantrian. remove: menghapus dan mengembalikan sebuah item dari antrian. Item yang dikembalikanadalahitemyangmempunyaiprioritastertinggi. isEmpty:memeriksaapakahantriannyakosongataukahtidak. Yangdimaksuddenganperbedaansemantikadalahbahwaitemyangtelahdihapusdari antrian tidaklah harus berupa item yang pertama kali dimasukkan/ ditambahkan. Sebaliknya,itemtersebutharusberstatussebagaiitemdenganprioritastertinggi.Apa yang dimaksud dengan prioritas, dan bagaimana mereka dibandingkan dengan satu sama lainnya tidak ditentukan oleh implementasi Antrian Prioritas. Semuanya tergantungdariitemitemapayangberadadidalamantriantersebut. Sebagaicontoh,jikaitemitemdidalamantreanmempunyainama,kitamungkinakan memilihmerekasecarasesuaiurutanalfabet.Jikamerekamerupakanskorpermainan bowling, kita mungkin memilih dari urutan tertinggi ke urutan terendah, tapi jika mereka itu skor permainan golf, mungkin kita akan memprioritaskan angka/item terendahkeyangtertinggi. Jadisekarangkitamempunyaimasalahbaru.Kitamenginginkansebuahimplementasi AntreanPrioritasyangsifatnyagenerikharusbisabekerjadenganobjekapapuntapi padasaatyangbersamaan,kodeyangmengimplementasikanAntrianPrioritasharus memilikikemampuanuntukmembandingkanobjekobjekyangdikandungnya.
351
Kita sudah melihat satu cara untuk mengimplementasikan struktur data generik menggunakanObject,tapiitutidakmenyelesaikanmasalahini,karenatidakadacara untukmembandingkanObjectkecualikitasudahtahuobjekitubertipeapa. JawabannyaterdapatdalamsebuahfiturJavayangdisebutmetaclass.
16.6 Metaclass
Metaclass adalah suatu kumpulan kelas yang menyediakan satu kumpulan metode. Definisimetaclassmengharuskansebuahkelasuntukmemenuhipersyaratanyangsudah ditentukanagarbisamenjadianggotadarisuatukumpulan. Terkadangmetaclassmetaclassmemilikinamayangdiakhiridengankataableuntuk mengindikasikan kemampuan dasar (fundamental) yang dibutuhkan oleh metaclass. Sebagai contoh, semua kelas yang menyediakan metode dengan nama draw bisa menjadi anggota dari metaclass Drawable. Semua kelas yang mengandung metode startbisamenjadianggotadarimetaclassRunnable. Java menyediakan sebuah metaclass bawaan yang bisa kita gunakan dalam sebuah implementasiuntukAntrianPrioritas.Metaclassinidisebut Comparable,danartinya sesuaidengannamanya.Semuakelasyangmenjadianggotametaclass Comparable harus menyediakan sebuah metode dengan nama compareTo yang mampu membandingkan dua objek lalu mengembalikan sebuah nilai yang mengindikasikan apakah satu argumen lebih besar atau lebih kecil ketimbang argumen lainnya, atau apakahkeduanyamerupakanduaargumenyangsama. UmumnyakelaskelasbawaanJavamerupakananggotadarimetaclass Comparable, termasukkelaskelaspembungkusnumeriksepertiIntegerdanDouble. DisubbabberikutnyasayaakanmenunjukkanbagaimanacaranyamenulissebuahADT
352
yangbisamemanipulasisebuahmetaclass.Lalukitaakanmelihatbagaimanacaranya menulissebuahkelasbaruyangakanmenjadianggotadarimetaclassyangsudahada. Di bab berikutnya kita akan melihat bagaimana caranya mendefinisikan sebuah metaclassbaru.
16.7 ImplementasiArrayuntukAntrianPrioritas
DalamimplementasiAntrianPrioritas,setiapkalikitamenentukantipeitemitemyang berada dalam antrian, kita menentukan metaclass Comparable. Sebagai contoh, variabelvariabelinstanberikutmerupakansebuaharrayyangberisiComparable dan sebuahinteger: publicclassPriorityQueue{ privateComparable[]array; privateintindex; }
Sepertibiasa,indexmerupakanindeksdariruangberikutnyayangmasihtersisa/kosong dalamarray.Variabelvariabelinstandideklarasikandengan private agarkelaskelas lainnyatidakbisamengaksesmerekasecaralangsung. Konstruktor dan isEmpty masih sama dengan yang pernah kita lihat sebelumnya. UkuranawaldariarraynyasilahkanAndatentukansendiri. publicPriorityQueue(){ array=newComparable[16]; index=0; } publicbooleanisEmpty(){ returnindex==0; 353
Satusatunyametodepentingdalamkelasadalahremove,yangharusmenelusuriarray untukmenemukanlalumenghapusitemterbesar:
public Comparable remove (){ if(index == 0)return null; intmaxIndex =0;
// find the index of the item with the highest priority for (int i=1; i<index; i++) { if (array[i].comp maxIndex =i; } } Comparable result =array[maxInd ex]; areTo (array[max Index]) >0){
354
]= array[index];
Ketikakitamenelusuriarray,maxIndexmenjagajejakelementerbesaryangsudahkita lihatsejauhini.Yangdimaksuddenganterbesardisiniakanditentukanolehmetode compareTo.Dalamkasusini,metodecompareTodisediakanolehkelasInteger,dania melakukan apa yang memang kita inginkan angka terbesar (lebih positif) adalah pemenangnya.
16.8 KlienAntrianPrioritas
ImplementasiAntrianPrioritasseluruhnyaditulismenggunakansusutpandangobjek objek Comparable,tapitidakadaobjekyangbisadisebutsebagaisebuahobjekdari metaclassComparable!Kalautidakpercaya,cobalahuntukmembuatsatuobjeksaja: Comparablecomp=newComparable();//ERROR Anda akan melihat pesan compiletime yang berbunyi java.lang.Comparable is an interface.Itcan'tbeinstantiated. DiJava,metaclassmetaclassjugadisebutdengan interface(antarmuka).Sampaisejauhinisayatelahmenghindarikatainikarenaiajuga memilikibeberapaartisekaligus,tapisekarangAndasemuaharustahu. Kenapametaclassmetaclassitutidakbisadiinstansiasi?Karenasebuahmetaclasshanya menentukan apaapa yang sudah disyaratkan (Anda harus mempunyai metode compareTo);iasendiritidakmenyediakansuatuimplementasi. Untuk membuat sebuah objek Comparable, Anda harus membuat satu objek yang dimilikiolehsatupaket Comparable,seperti Integer.KemudianbarulahAndabisa menggunakanobjektersebutdimanapunmetaclassComparabledipanggil. PriorityQueuepq=newPriorityQueue(); 355
Integeritem=newInteger(17); pq.add(item); KodeiniakanmembuatsatuAntrianPrioritasyangbarusekaliguskosong,jugasebuah objek Integer. Kemudian kode ini akan menambahkan Integer ke dalam antrian. Metode add mengharapkansebuah Comparable sebagaisebuahparameter,jadidia dengansenanghatimenerimasebuah Integer.Jikakitamencobauntukmelewatkan sebuah Rectangle yang bukan merupakan anggota Comparable, kita akan mendapatkan sebuah pesan compiletime yang berbunyi, Incompatible type for method.Explicitcastneededtoconvertjava.awt.Rectangletojava.lang.Comparable. Itulahyangdikatakanolehcompilerkepadakita.Jadi,jikakitainginmembuatkonversi itu terjadi, maka kita harus melakukannya secara eksplisit. Kita mungkin akan melakukanapayangdikatakanolehcompilertersebut: Rectanglerect=newRectangle(); pq.add((Comparable)rect);
Tetapididalamkasussepertiinikitajustrumenerimapesanerroryangterkaitdengan ClassCastException. Ketika Rectangle mencoba untuk melewatkan sebagai sebuah Comparable, sistem runtime akan memeriksa apakah cara ini memenuhi semua persyaratan,lalumenolaknya.Jadi,itulahyangakankitadapatkanjikakitamengikuti sarandaricompiler. Untukmengeluarkanitemitemdariantrian,kitaharusmembalikprosesnya: while(!pq.isEmpty()){ item=(Integer)pq.remove(); System.out.println(item); } 356
Perulangan ini menghapus semua item dari antrian lalu mencetaknya. Proses ini mengasumsikanbahwaitemitem yangberadadidalamantrian merupakan Integer. Karena jika mereka bukan ClassCastException. Integer, kita akan mendapatkan sebuah
16.9 KelasGolfer
Akhirnya,marikitalihatbagaimanacaranyamembuatsebuahkelasbaruyangakan menjadi anggota Comparable. Sebagai sebuah contoh atas sesuatu dengan definisi yangtidakbiasatentangprioritastertinggikitaakanmenggunakanparapemaingolf (golfers): publicclassGolferimplementsComparable{ Stringname; intscore; publicGolfer(Stringname,intscore){ this.name=name; this.score=score; } } Definisi kelas dan konstruktor selalu hampir sama dengan yang sudah kita buat sebelumnya;bedanyaadalahkarenauntuksaatinikitaharusbisamembuatdeklarasi agar kelas Golfer bisa mengimplementasikan metaclass Comparable (Golfer implementComparable).DalamkasusinikatakunciimplementberartibahwaGolfer mengimplementasikanantarmukayangditentukanolehComparable.
357
Jikasekarangkitamencobauntukmengcompile Golfer.java,kitaakanmendapatkan pesan yang berbunyi class Golfer must be declared abstract. It doesn't define int compareTo(java.lang.Object)frominterfacejava.lang.Comparable.Dengankatalain, agar bisa menjadi Comparable, Golfer harus menyediakan sebuah metode dengan namacompareTo.Oke,kalaubegitu,marikitatulissekarangjuga: publicintcompareTo(Objectobj){ Golferthat=(Golfer)obj; inta=this.score; intb=that.score; //dalamgolf,yangkecilitulebihbaik if(a<b)return1; if(a>b)return1; return0; } Duahalyangadadisinimembuatkitasedikitterkejut.Satu,parameternyamerupakan sebuah Object.Inikarenasecaraumumsipemanggiltidakmengetahuiobjekbertipe apayangsedangdibandingkan.Sebagaicontoh,dalamPriorityQueue.java,ketikakita memanggilcompareTo,kitajugamelewatkansebuahComparablesebagaiparameter. KitatidakperlutahuapakahiatermasukInteger,Golfer,atauapapunitu. Di dalam compareTo,kita harusmengubah parameterdari sebuah Object menjadi Golfer.Sepertibiasa,akanadarisikoketikakitamenggunakantipecastsepertiini:jika kitamengcastketipeyangsalahmakakitaakanmendapatkanpesaneksepsi. Akhirnya,kitabisamembuatbeberapapemaingolf:
358
Golfertiger=newGolfer("TigerWoods",61); Golferphil=newGolfer("PhilMickelson",72); Golferhal=newGolfer("HalSutton",69); Lalumemasukkanmerekakedalamantrian: pq.add(tiger); pq.add(phil); pq.add(hal); Ketikakitamengeluarkanmereka: while(!pq.isEmpty()){ golfer=(Golfer)pq.remove(); System.out.println(golfer); } Merekaakanditampilkandalamurutanterbalik(khususuntukpemaingolf): TigerWoods HalSutton PhilMickelson 61 69 72
KetikakitaberalihdariIntegerkeGolfer,kitatidakperlumembuatperubahanapapun dalam PriorityQueue.java. Sama sekali tidak! Jadi sekarang kita telah berhasil mengatasi jurang antara PriorityQueue dan kelaskelas yang menggunakannya. Dengan kondisi ini, kita bisa menggunakan ulang kode tersebut tanpa harus mengubahnya.Lebihjauhlagi,kitabisamemberikankendalikepadakodeklienmelalui definisiyangsudahkitabuatuntukcompareTo.Dengancarasepertiini,implementasi PriorityQueueakanmenjadilebihadaptif. 359
16.10 DaftarKataKata
Istilah queue queueingdiscipline Arti Sekumpulanobjekyangsedangmenantikansuatulayanan atausejenisnya. Aturanyangmenentukananggotaantrianmanayangakan dihapuslebihdulu. firstinfirstout,sebuahaturanantriandimanaanggota FIFO yangpertamakalidatangakanmenjadiyangpertamakali dihapus. Suatuaturanantriandimanasetiapanggotanyamempunyai priorityqueue prioritas yang ditentukan oleh faktorfaktor eksternal. Anggotayangmempunyaiprioritastertinggiadalahanggota yangpertamakalikitahapus. Sebuah ADT yang mendefinisikan operasioperasi yang PriorityQueue mungkin akan dilakukan oleh seseorang terkait dengan antrianberprioritas. Suatu definisi kelas yang mengimplementasikan sebuah ADTdengandefinisidefinisimetodeyangmerupakanhasil veneer pemanggilandarimetodemetodelainnya,terkadangdengan beberapaperubahankecil.Veneertidakmengerjakanfungsi yang signifikan, tapi dia bisa meningkatkan atau menstandardisasiantarmukayangdilihatolehklien. Bahaya yang terkait dengan penggunaan veneer ketika performancehazard beberapametodemungkindiimplementasikansecaratidak efisiensehinggametodetersebutjustrumalahtidaktampak olehklien. 360
Operasi yang memiliki runtime yang tidak bergantung kepadaukuranstrukturdatanya. Operasiyangruntimenyaberupafungsilineardariukuran strukturdatanya. Implementasiantrianmenggunakanlinkedlistdanacuanke nodepertamadanterakhir. Implementasi antrian menggunakan array dan indeks dari
circularbuffer
metaclass
interface
16.11 Latihan
Latihan16.3 PertanyaaniniberdasarkanLatihan9.3. TulislahsebuahcompareTountukkelasRationalyangmemungkinkanRationaluntuk mengimplementasikanComparable. Petunjuk:janganlupabahwaparameteradalahsebuahObject.
Latihan16.4 Tulislah definisi kelas untuk SortedList yang merupakan perluasan dari kelas LinkedList.SortedListsamadenganLinkedList;bedanya,elemenelemenSortedList 361
Latihan16.5 Tulislahsatumetodeobjek, maximum,untukkelas LinkedList yangbisadipanggil melaluiobjekLinkedList.Metodeinibisamengembalikanobjekkargoterbesardalam list,ataunulljikalistnyakosong. Anda bisa mengasumsikan bahwa semua elemen kargo menjadi milik kelas yang menjadianggotametaclassComparable,dansetiapduaelemenbisadibandingkansatu samalainnya.
Latihan16.6 Tulislah implementasi untuk Antrian Prioritas menggunakan linked list. Ada tiga tahapanyangharusAndaproses:
Antrian Prioritas mungkin berisi sebuah objek LinkedList sebagai sebuah variabelinstan.
AntrianPrioritasmungkinberisisebuahacuankeobjekNodepertamadalam linkedlist.
AntrianPrioritasdiwarisidarikelasLinkedListyangsudahada.
Pikirkanmengenaiprodankontradariketigatahapandiataskemudianpilihlahsalah satu diantaranya.Selainitu, Andajuga bisamemilih; untukmenjagalist agar tetap terurut(slowadd,fastremove),atautidakterurut(slowremove,fastadd). 362
Latihan16.7 AntrianKegiatanadalahsebuahstrukturdatayangmenjagaurutankegiatan,dimana setiap kegiatan mempunyai waktu pelaksanaan yang terkait dengannya. Berikut ini adalahADTnya: constructor:membuatantriankegiatanyangbarudankosong add: menambahkan sebuah kegiatan baru ke dalam antrian. Parameternya adalah kegiatan yang merupakan sebuah Object, dan waktu pelaksanaan kegiatan tersebut yangberupaobjekDate.Objekkegiatannyatidakbolehbernilainull. nextTime: mengembalikan Date untuk pelaksanaan kegiatan berikutnya, kegiatan berikut di sini adalah kegiatan di dalam antrian yang dimulai lebih dulu. Jangan menghapuskegiataninidariantrian.Kembalikannilainulljikaantriannyakosong. nextEvent: mengembalikan kegiatan berikutnya (sebuah Object) dari antrian lalu menghapusnyadariantrian.Kembalikannilainulljikaantriannyakosong. Kelas Date didefinisikandalam java.util.Kelasinimengimplementasikanmetaclass Comparable.Menurutdokumentasinya,metodecompareTonyamengembalikanthe value0iftheargumentDate isequaltothisDate;avaluelessthan0ifthisDateis before theDateargument;andavalue greaterthan0ifthisDateisaftertheDate argument. Tulislah sebuah implementasi untuk antrian kegiatan menggunakan ADT PriorityQueue.AndatidakbolehmembuatasumsimengenaibagaimanaPriorityQueue diimplementasikan. Hint:buatlahsebuahkelas,Event,yangberisiDatedansebuahObjectkegiatan.Kelas iniharusmengimplementasikanComparabledengantepat.
363
Puncakpohon(simpulyangdiacudengannamatree)disebutakar(root).Agarsesuai 364
denganistilahistilahdalamduniaperpohonan(baca:metaforapohon),simpulsimpul lainakandisebutcabangcabang(branches).Sementarasimpulyangberadadiposisi bagianbawahyangmengacukenulldisebutdaundaun(leaves).Mungkindisinikita telahmelakukansesuatuyangganjildenganmenggambarakardiatassementaradaun daunmalahdibawah.Tapitunggudulu,itubukanlahhalteraneh. Untukmembuatnyalebihanehlagi,ilmuwankomputermengombinasikannyadengan metaforalain:pohonkeluarga(thefamilytree).Simpulyangberadadiatasbiasanya disebut parent (induk) sementara simpulsimpul yang diacunya disebut children (anak). Simpulsimpul dengan induk yang sama disebut siblings, begitu juga sebaliknya. Akhirnya, kita juga akan menjumpai kosakata bidang geometri ketika berbicara mengenaipohon.Sayasudahmenyebutkankanandankiri,dansekarangadalagiup (menujukeinduk/akar)dandown(menujukeanak/daun).Selainitu,semuasimpul yangmempunyaijarakyangsamadariakarmerupakanleveldarisebuahpohon. Sayasendiritidaktahukenapakitaharusmenggunakantigametaforasekaligusketika berbicaratentangpohon,tapiitulahfaktayangada.
17.2 MembuatPohon
Prosespenyusunansimpulsimpulpohonmiripdenganprosesketikakitamerangkai list. Kita mempunyai sebuah konstruktor untuk simpulsimpul pohon yang menginisialisasivariabelvariabelinstan. publicTree(Objectcargo,Treeleft,Treeright){ this.cargo=cargo; this.left=left; this.right=right; } 365
17.3 MenelusuriPohon
Carapalingalamiuntukmenelusurisebuahpohonadalahdenganmemakaimetodeyang rekursif.Sebagaicontoh,untukmenambahkansemuaintegerkedalamsatupohon,kita bisamenulismetodekelassebagaiberikut: publicstaticinttotal(Treetree){ if(tree==null)return0; Integercargo=(Integer)tree.cargo; return cargo.intValue() total(tree.right); } Metode diatasmerupakan metodekelaskarenakitaakan menggunakan null untuk merepresentasikanpohonyangkosong.Nantinya,pohonkosonginilahyangakankita jadikanbasecasemetoderekursifkita.Jikasuatupohondiketahuikosong,metodekita akan mengembalikan nilai0. Kalau tidak, metodeini akan membuat dua panggilan bersifatrekursifuntukmenemukannilaitotaldariduaanaknya.Akhirnya,metodeini akanmenambahkannilaitotalinikedalamkargonyalalumengembalikannilaitotal. 366 + total (tree.left) +
Meskipun metode ini bekerja dengan baik, ada beberapa kesulitan yang akan menghadang kita ketika kita hendak mengimplementasikannya dengan konsep pemrogramanberorientasiobjek.Metodeiniharusnyatidakbolehmunculdalamkelas Tree karena ia membutuhkan kargo untuk menjadi objekobjek Integer. Jika kita membuatasumsiinidalamTree.javamakakitaakankehilanganmanfaatmanfaatyang bisakitaambildaripenggunaanstrukturdatagenerik. Disisilain,kodeinimengaksesvariabelvariabelinstansimpulsimpulpohon.Jadidia mengetahuilebihbanyakketimbangyangseharusnyamengenaiimplementasisuatu pohon. Jika kita mengubah implementasi ini, kodenya nanti rusak (baca: tidak bisa dipakai). Nanti di bagian lain dalam bab ini, kita akan mengembangkan sebuah cara untuk menyelesaikan masalah ini, membolehkan kode klien untuk menelusuri pohon yang berisi objek apapun tanpa merusak perbedaan abstraksi antara kode klien dan implementasinya.Sebelumkitasampaikesana,marikitamelihatsebuahaplikasiyang memanfaatkankonseppohonini.
17.4 PohonEkspresi
Pohonmerupakancaraalamiuntukmerepresentasikanstruktur/susunansuatuekspresi matematika.Tidaksepertinotasidalambidanglain,pohonmampumerepresentasikan proseskomputasitanpaharusmendatangkanambiguitas.Sebagaicontoh,ekspresiinfix untuk1+2*3termasukyangmendatangkanambiguitas,kecualikalaukitamengetahui bahwaunsurperkaliandiproseslebihdahuluketimbangunsurpenjumlahan. Gambarberikutinimenunjukkankomputasiyangsama:
367
Simpulsimpuldiatasbisasajamerupakansebuahoperanseperti1dan2atauberupa operatoroperator seperti + dan *. Operanoperan merupakan simpulsimpul daun; sementarasimpulsimpuloperatorberisiacuanyangmengacukeoperanoperanmereka (semuaoperatordisinidisebutoperator biner (binary),karenamerekamempunyai tepatduaoperan). Berdasarkan gambar di atas, tidak usah ditanya lagi bagaimana urutan operasi ini terjadi:unsurperkaliandikerjakanterlebihdahulusebelumprosespenjumlahanterjadi. Pohonekspresisepertiinimempunyaibanyakmanfaat.Contohyangakankitalihat adalahdalamprosespengubahan(baca:penerjemahan)darisatuformat(postfix)ke formatlainnya(infix).Pohonpohonyangsamadigunakandidalam compiler untuk melakukanprosespenguraian(parse),optimalisasidanmenerjemahkanprogram.
17.5 Penelusuran
Sayasebelumnyasudahmenunjukkanbahwarekursisebenarnyamerupakancarayang alamiuntukmenelusurisatupohon.Kitabisamencetakisisuatupohonekspresidengan carasepertiini: 368
publicstaticvoidprint(Treetree){ if(tree==null)return; System.out.print(tree+""); print(tree.left); print(tree.right); } Dengan kata lain, untuk mencetak satu pohon, langkah pertama adalah dengan mencetak isi akarnya, lalu mencetak semua subpohon sebelah kiri, baru kemudian mencetakseluruhsubpohonyangadadibagiankanan.Carapenelusuransepertiini disebutpreorder,karenaisidariakarmunculsebelumisianakanaknyamuncul. Untukekspresicontohtadi,outputnyaadalah+1*23.Hasiliniberbedadarihasilyang didapat ketika menggunakan postfix atau infix; output ini adalah notasi baru yang dikenal dengan istilah prefix. Dalam notasi ini, operatoroperator muncul sebelum operanoperanmereka. Andamungkinsudahmendugabahwajikakitamenelusuri suatu pohon dengan urutan yangberbedamakakitaakanmendapatkanekspresidalamnotasiyangberbedapula. Sebagaicontoh,jikakitamencetaksubpohondulu,laludilanjutkandengansimpulakar: publicstaticvoidprintPostorder(Treetree){ if(tree==null)return; printPostorder(tree.left); printPostorder(tree.right); System.out.print(tree+""); } Kita akan mendapatkan ekspresi postfix (1 2 3 * +)! Seperti namanya, urutan 369
penelusuransepertiinidisebut postorder.Akhirnya,untukmenelusurisebuahpohon secara inorder, kita cetak dulu bagian kiri pohon, kemudian akar, diakhiri dengan bagiankanannya: publicstaticvoidprintInorder(Treetree){ if(tree==null)return; printInorder(tree.left); System.out.print(tree+""); printInorder(tree.right); }
Hasilnyaadalah1+2*3,yangmerupakanekspresiinfix. Jujur saja, saya harus mengatakan bahwa sebenarnya saya telah mengacuhkan komplikasipenting.Terkadang,ketikakitamenulissebuahekspresiinfix,kitaharus menggunakan tanda kurung (parentheses) untuk menjaga urutan operasioperasinya. Jadi, penelusuran secara inorder belumlah cukup untuk menghasilkan satu ekspresi infix. Meskipunbegitu,denganbeberapaperbaikan,pohonekspresidanketigapenelusuran rekursiftersebutmampumemberikanteknik/carayangumumuntukmenerjemahkan ekspresidarisatuformatkeformatlainnya.
17.6 Enkapsulasi
Sepertiyangsudahsayakatakansebelumnya,masihadamasalahdenganteknik/cara yang kita ambil dalam menelusuri pohonpohon: cara ini membuat kita harus memisahkan kode klien (aplikasi yang menggunakan pohon) dengan kode provider (implementasiPohon).Idealnya,suatupohonharusnyabersifatumum;iatidakharus
370
tahusegalasesuatutentangpohonpohonekspresi.Sementarakodeyangmenghasilkan sekaligus menelusuri pohonpohon ekspresi tidak perlu tahu segala sesuatu tentang implementasi pohonpohon. Prinsip/standar perancangan seperti ini disebut object encapsulation(enkapsulasiobjek).IstilahinidigunakanagarAndatidakkebingungan denganistilahyangsudahadadalamsubbab6.6,yaknimethodencapsulation. Untukversisaatini,kodeTreetahuterlalubanyaktentangkliennya.Sebaliknya,kelas Treeharusmenyediakankemampuan/kapabilitasumumuntukmelakukanpenelusuran satupohondenganberagamcara.Ketikapenelusuransedangdilakukan,iaharusbisa memprosesoperasidisetiapsimpulyangditentukanolehklien. Untukmemfasilitasiperbedaankepentinganini,kitaakanmembuatsebuahmetaclass baruyangdisebutVisitable.Itemitemyangdisimpandalamsebuahpohondisyaratkan agar bisa dikunjungi (visitable). Ini berarti bahwa itemitem tersebut akan mendefinisikansebuahmetodevisityangakanmelakukanapapunyangdiinginkan olehklienterhadapmasingmasingsimpul.Dengancaraini,Pohonkitaakanmampu melakukanpenelusuransementaraklienmampumengerjakanoperasioperasisimpul. Berikutiniadalahlangkahlangkahyangharuskitakerjakanuntukmembuatmetaclass yangbisadigunakanolehkeduakubusekaligus,kliendanprovider: 1. Definisikanlahsebuahmetaclassyangmampumengidentifikasimetodemetode yang akan dibutuhkan oleh kode provider untuk melakukan pemanggilan melaluikomponenkomponennya. 2. Tulislahkode provider sebagaisatumetaclassyangbaru,sebagailawandari Objectyangbersifatgenerik. 3. Definisikanlahsebuahkelasyangmenjadibagiandarimetaclassdanmampu mengimplementasikanmetodemetodeyangmemangdibutuhkanolehklien. 4. Tulislahkodeklienuntukmenggunakankelasyangbarutersebut. 371
Subbabberikutnyaakanmendemonstrasikanlangkahlangkahini.
17.7 Mendefinisikanmetaclass
Sebenarnya terdapat dua cara untuk mengimplementasikan sebuah metaclass dalam Java,sebagaiinterfaceatausebagaiabstractclass.Perbedaanantarakeduanyatidaklah terlalu penting untuk saat ini, jadi kita akan mulai dengan mendefinisikan sebuah antarmuka(interface). Definisiantarmukatampaksepertidefinisikelas,denganduaperbedaan:
katakunciclassdigantidenganinterface,dan definisimetodetidakmempunyaibadan(bodies).
Definisi antarmuka menentukan metodemetode yang harus diimplementasikan oleh sebuahkelasagarbisamenjadianggotametaclass.Syaratsyaratyangharusdipenuhi antaralain;nama,tipetipeparameter,dantipepengembaliandarisetiapmetode. DefinisiVisitableadalahsebagaiberikut publicinterfaceVisitable{ publicvoidvisit(); } Itusaja,cukup!Definisi visit tampaksepertidefinisimetodepadaumumnya,kecuali bahwa sekarang kita tidak memerlukan badan. Definisi ini mengindikasikan bahwa semuakelasyangmengimplementasikan Visitable harusmempunyaimetodedengan namavisityangtidakmembutuhkanparameterapapundanmengembalikanvoid. Sepertidefinisikelaslainnya,definisiantarmukamemilikinamafileyangsamadengan namakelasnya(dalamhaliniVisitable.java).
372
17.8 MengimplementasikanMetaclass
Jika kita menggunakan sebuah pohon ekspresi untuk menghasilkan infix, maka mengunjungisatusimpulberartimencetakisiisinya.Karenaisidarisebuahpohon ekspresi berupa token, kita akan membuat kelas baru yakni Token yang mengimplementasikanVisitable. publicclassTokenimplementsVisitable{ Stringstr; publicToken(Stringstr){ this.str=str; } publicvoidvisit(){ System.out.print(str+""); } } Ketika kita mengcompile definisi kelas ini (yang berada dalam file Token.java), compiler akan memeriksa apakah metodemetode itu memenuhi persyaratan yang ditentukanolehmetaclass.Jikatidak,iaakanmenyebabkanmunculnyapesan error. Sebagai contoh, jika kita salah menyebutkan nama metode yang dikira visit, kita mungkinakanmenerimasesuatuseperti,classTokenmustbedeclaredabstract.Itdoes not definevoidvisit()frominterfaceVisitable.Ini adalahsatudarisekianbanyak pesan error yangsolusinyatidaktepat.Ketika compiler tersebutmengatakanbahwa suatukelasmustbedeclaredabstract,apayangdimaksuddenganpernyataantersebut adalah bahwa Anda harus memperbaiki kelas itu sehingga ia mengimplementasikan antarmukadengantepat.Terkadangsayasampaiberpikiruntukmelawanorangyang 373
menulispesanini. LangkahberikutnyaadalahmemodifikasiparseruntukmeletakkanobjekobjekToken kedalampohonketimbangString.Berikutinicontohkecilnya: Stringexpr="123*+"; StringTokenizer +*/",true); Stringtoken=st.nextToken(); Tree tree = new Tree (new Token (token), null, null)); Kode ini menggunakan token pertama dalam string lalu membungkusnya ke dalam objekToken,kemudianmeletakkanTokentersebutkedalamsatusimpulpohon.Jika TreedisinimembutuhkankargoagarbisamasukkedalammetaclassVisitable,iaakan mengubah Token sehingga bisa menjadi bagian dari objek Visitable. Ketika kita menghapusVisitabledaripohon,kitaharusmengcastnyakembalikebentukToken. Latihan17.1 TulislahversiprintPreorderdengannamavisitPreorderyangmenelusuripohondan memanggilvisitdisetiapsimpuldalampreorder. Alureksekusiuntukmetodemetodeseperti visitPreorder tampaktidakbiasa.Klien memanggilsebuahmetodeyangdisediakanolehimplementasiTree,laluimplementasi Tree ini akan memanggilsatu metode yang disediakanoleh klien. Pola seperti ini disebut callback;adalahlangkahyangbaikuntukmembuatkode provider yanglebih umumtanpaharusmemecahabstraksiyangsudahdibuat. st = new StringTokenizer (expr, "
17.9 KelasVector
Vector merupakankelasbawaanJavayangberadadalampaket java.util.Kelasini 374
merupakanimplementasidarisebuaharrayyangberisiObjectdenganfiturtambahan, yakni kemampuan untuk mengubah ukurannya secara otomatis, sehingga kita tidak perlucapekcapekmelakukannya. Sebelum menggunakan kelas Vector ini, Anda harus memahami beberapa konsep terlebihdahulu.SetiapVectormempunyaikapasitasmasingmasing,yakniruangyang sudahdialokasikanuntukmenyimpannilainilaidanukuranyangmerupakanbanyak nilaiyangberadadalamvektor. Gambarberikutinimerupakandiagramsederhanadarisebuahvektoryangberisitiga elemen,tapikapasitasnyatujuh.
Adaduakelompokmetodeuntukmengakseselemenelemenyangberadadalamvektor. Metodemetodetersebutmenyediakansemantikdankemampuan errorchecking yang berbedabeda.Hatihati,mungkinmerekaakanseringmembuatAndakebingungan. Metodepalingsederhanaadalah get dan set.Duametodeinimenyediakansemantik yang mirip dengan apa yang dimiliki oleh operator indeks array, []. Metode get menggunakanindeksintegerdanmengembalikanelemenyangberadapadaposisiyang diinginkan. Sementara set menggunakan sebuah indeks dan satu elemen, lalu menyimpan elemen yang baru itu pada posisi yang diinginkan, mengganti elemen sebelumnyayangsudahberadadidalamposisiitu. Metode get dan set tidakdigunakanuntukmengubahukuranvektor(jumlahelemen). Hal ini merupakantanggungjawabkodeklienuntukmemastikanagarsuatuvektor mempunyai ukuran yang cukup sebelum get dan set dipanggil. Metode size mengembalikanjumlahelemenyangadadalamvektor.JikaAndamencobamengakses satuelemenyangtidakeksis/ada(yaituelemendenganindeks3sampai6),Andaakan 375
menerimaeksepsiArrayIndexOutOfBounds. Kumpulanmetodelainmengikutsertakanbeberapaversidariadddanremove.Metode metodeinimampumengubahukuranvektordankapasitasnya,jikadiperlukan.Salah satuversidariaddmenggunakansatuelemensebagaiparameterlalumenambahkannya ke ujung vektor (baca: bagian belakang). Metode ini lebih aman karena tidak menyebabkaneksepsi. Versi lain dari add menggunakan satu indeks dan satu elemen. Seperti set, ia meletakkan elemen baru di posisi yang diinginkan. Bedanya, add tidak mengganti elemenyangsudahadasebelumnya.Metodeiniakanmenaikkanukuranvektor,lalu menggeser elemenelemen yang ada ke sebelah kanan untuk memberi ruang bagi elemen yang baru. Oleh karena itu, pemanggilan metode seperti ini; v.add (0, elt) berartimenambahkanelemenbarudiawalvektor.Sayangnya,metodeiniselaintidak aman juga kurang efisien; ia bisa menyebabkan eksepsi berupa ArrayIndexOutOfBounds dan,dalambanyakimplementasi,metodeinitermasukke dalamlineartime(sesuaidenganukuranvektornya). Secaraumum,paraklientidakperlukhawatirmengenaikapasitas.Kapanpunukuran vektorberubah,kapasitasakandiperbaharuisecaraotomatis.Karenaalasanunjukkerja, beberapaaplikasimemegangkendaliatasfungsiini,yangsekaligusmenjadipenyebab kenapaadametodemetodetambahanuntukmenaikkandanmenurunkankapasitas. Karenakodeklientidakmempunyaiaksesuntukmenggunakanimplementasivektor, adalahtidakjelasbagaimanacarakitamenelusurinya.Tentusaja,satukemungkinan adalahdenganmemakaivariabelperulangansebagaiindeksuntukvektor: for(inti=0;i<v.size();i++){ System.out.println(v.get(i)); }
376
Tidakadayangsalahdengankodediatas,tapiadacaralainyangjugabisadigunakan untuk mendemonstrasikan kelas Iterator. Vektorvektor menyediakan satu metode, yakni iterator, yang bisa mengembalikan objekobjek Iterator sehingga memungkinkanmetodeiniuntukmelakukanpenelusuranvektor.
17.10 KelasIterator
Iteratoradalahantarmukayangberadadalamjava.util.package.Antarmukainiterdiri daritigametode: hasNext:apakahiterasiinimempunyaielemenyanglebih? next: mengembalikan elemen berikutnya, atau mengembalikan sebuah eksepsi jika kosong remove:menghapuselemenyangpalingbarudaristrukturdatayangkitatelusuri Contoh berikut ini menggunakan sebuah iterator untuk menelusuri dan mencetak elemenelemenyangterdapatdalamsatuvektor. Iteratorit=vector.it(); while(it.hasNext()){ System.out.println(it.next()); } Setelah Iterator dibuat, ia akan menjadi objek yang terpisah dari Vector aslinya. Perubahanyangterjadiberikutnyatidakakanmemengaruhi Iterator itusendiri.Pada kenyataannya,jikaAndamemodifikasiVectorsetelahmembuatIterator,Iteratoritu akan menjadi tidak valid. Jika Anda mengakses Iterator itu lagi, hal ini akan menyebabkaneksepsiConcurrentModification.
377
Dalamsubbabsebelumnyakitamenggunakanmetaclass Visitable untukmengizinkan satu klien menelusuri struktur data tanpa harus mengetahui detail implementasinya. Iteratoriterator menyediakan cara lain bagi kita untuk melakukan hal yang sama. Dalamkasusyangpertama, provider melakukanperulangannyalalumemanggilkode klienuntukmengunjungimasingmasingelemen.Dalamkasusberikutnya, provider memberikankliennyasatuobjekyangbisadigunakannyauntukmemilihsatuelemen padasuatuwaktu. Latihan17.2 Tulislah sebuah kelas, PreIterator, yang mengimplementasikan antarmuka Iterator lalubuatlahsebuahmetode,preorderIteratoruntukkelasTree yangmengembalikan satuPreIteratoryangmampumemilihelemenelemenTreesecarapreorder. PETUNJUK: CaratermudahuntukmembuatIteratoradalahdenganmeletakkanelemenelemenke dalam sebuah vektor yang urutannya sesuai dengan apa yang Anda inginkan. KemudianAndabisamemanggilmetodeiteratormelaluivektortersebut.
17.11 DaftarKataKata
Istilah binarytree root leaf parent Arti Pohonyangtiapsimpulnyamengacuke0,1,atau2simpul yangsalingterkaitsatusamalainnya. Simpultertinggiyangadapadasebuahpohon,yangtidak diacuolehsimpulmanapun. Simpulterbawahpadasebuahpohonyangtidakmengacuke simpulmanapun.. Simpul yang mengacu ke salah satu atau banyak simpul
378
dalampohon. child level preorder postorder Salahsatusimpulyangdiacuolehsimpullainnya. Kumpulansimpulyangmasingmasingmemilikijarakyang samakeroot. Sebuah teknik penelusuran pohon di mana setiap simpul dikunjungilebihdahulusebelumsimpulanakanaknya. Sebuah teknik penelusuran pohon; kunjungi simpul anak darisemuasimpulsebelumsimpulitusendiri. Sebuah teknik penelusuran pohon; kunjungi subpohon inorder bagian kiri,kemudianakarnya,lalubarukunjungibagian kanannya. linkedqueue classvariable binaryoperator Implementasiantrianmenggunakanlinkedlistdanacuanke nodepertamadanterakhir. Variabelstaticyangdideklarasikandiluarsemuametode. Variabelinibisadiaksesdarimetodemanapun. Operatoryangmenggunakanduaoperan. Suatu rancangan yang tujuannya adalah untuk menjaga implementasi dari satu objek agar selalu terpisah dari objectencapsulation implementasiobjeklainnya.Begitujugadengankelas.Satu kelas tidak harus mengetahui detail implementasi kelas lainnya. Suatu rancangan yang tujuannya adalah untuk menjaga methodencapsulation antarmuka dari suatu metode terpisah dari detail implementasinya. callback Alur eksekusi di mana kode provider memanggil sebuah metodeyangdisediakanolehklien.
379
17.12 Latihan
Latihan17.3 a) Apahasilekspresipostfix12+3*? b) Ekspresipostfixapayangekuivalendenganekspresiinfix1+2*3? c) Apa hasil ekspresi postfix 17 1 5 /, asumsikan bahwa simbol / melakukan pembagianinteger?
TulislahmetodeheightyangbisamenghitungtinggidariparameteryangberupaTree.
Latihan17.5 Bayangkan kita sedang mendefinisikan sebuah Tree yang berisi objekobjek Comparablesebagaikargo: publicclassComparableTree{ Comparablecargo; Treeleft,right; }
Tulislah metode kelas Tree, findMax, yang mengembalikan kargo terbesar dalam 380
pohon.KataterbesardisiniditentukanolehmetodecompareTo. Latihan17.6 Pencarianbinerpohonmerupakanpohonkhususdimanasetiapsimpulpohon N: semuakargodisebelahkirisubpohonN<kargodalamsimpulN dan kargoyangadadisimpulN<semuakargodisebelahkanansubpohonN Dengan menggunakan definisi kelas seperti di atas, buatlah sebuah metode objek contains yangmenggunakansatu Object sebagaiargumenlalumengembalikannilai True jika objeknya muncul dalam pohon, atau False jika tidak. Anda bisa mengasumsikanbahwaobjekyangmenjaditargetdansemuaobjekyangberadadalam pohonmerupakananggotadarimetaclassComparable. publicclassSearchTree{ Comparablecargo; SearchTreeleft,right; }
Latihan16.7 Dalammatematika,satuhimpunan(set)merupakansuatukumpulanelemenyangtidak ada duplikasi di dalamnya. Antarmuka java.util.Set digunakan untuk memodelkan himpunanmatematika.Metodeyangdibutuhkannyaadalahadd,contains,containsAll, remove,size,daniterator. Tulislah kelas TreeSet yang mewarisi kelas SearchTree sekaligus mampu mengimplementasikanSet.Agarsemuanyabisatetapberjalandengansederhana,Anda bisamengasumsikanbahwanulltidakakanmunculdalampohonatausebagaiargumen 381
darimetodemanapun. Latihan17.8 Tulislah metode union yang menggunakan dua Set sebagai argumen lalu mengembalikansebuahTreeSetbaruyangberisisemuaelemenyangmunculdikedua Setitu. Anda bisa memasukkan metode ini ke dalam implementasi TreeSet, atau membuat kelasbaruyangmewarisijava.util.TreeSetyangmenyediakanuniondidalamnya. Latihan17.9 Tulislah metode intersection yang menggunakan dua Set sebagai parameter lalu mengembalikansebuah TreeSet baruyangberisisemuaelemenyangmunculdalam keduaSettersebut. Metode union dan intersection bersifatgenerikkarenaparameterparameternyabisa bertipeapasajadalammetaclassSet.Bahkankeduaparameteritutidakharusmemiliki tipeyangsama. Latihan17.10 Salah satu alasan kenapa antarmuka Comparable bermanfaat adalah karena ia mengizinkan satu tipe objek untuk memutuskan bahwa semua teknik pengurutan sebenarnyatepat.UntuktipetipesepertiIntegerdanDouble,teknikpengurutanyang tepatsudahjelas,tapiadabanyakcontohdimanasuatupengurutanbergantungpada apayangingindirepresentasikanolehsiobjek.Dalamgolf,sebagaicontohsaja,skor yanglebihrendahlebihbaikketimbangyanglebihtinggi;jikakitamembandingkandua objekGolfer,objekyangmempunyaiskorlebihrendahakanmenjadipemenangnya. a) Tulislah definisikelas Golfer yang berisi nama dan skor bertipe integer sebagai variabel instan. Kelas ini harus mengimplementasikan Comparable dan
382
menyediakanmetodecompareToyangbisamemberikanprioritaslebihtinggiuntuk skoryanglebihrendah. b) Tulislahsebuahprogramyangbisamembacafileyangberisinamanamadanskor skor dari kumpulan(Set) pegolf.Programiniharusbisamembuatobjek Golfer, meletakkanobjekobjektersebutkedalamAntrianPrioritaslalumengeluarkandan mencetak mereka. Mereka harus ditampilkan dalam urutan terbalik (descending) berdasarkanprioritas.Halinisamasajadengankenaikanurutanberdasarkanskor. TigerWoods HalSutton PhilMickelson AllenDowney PETUNJUK: LihatbagianCuntukkodeyangbisamembacabarisbarisdalamsuatufile. Latihan17.11 Tulislah implementasi Stack menggunakan Vector. Coba pikirkan, apakah memasukkan (push) elemen baru ke posisi awal stack akan lebih baik ketimbang memasukkannyakeposisiterakhir? 61 69 72 158
383
Jadiapasajaoperasioperasipohonitu?Dengankatalainbagaimana mendefinisikan pohonADT? constructor:Membangunsebuahpohonkosong. getLeft:Mengembalikananakkiridarisimpul. getRight:Mengembalikananakkanandarisimpul. getParent:Mengembalikanorangtuadarisimpul. getCargo:Mengembalikanmuatandarisimpul. setCargo:Memasukkansebuahobjekmuatanpadasimpulini(dan membuatsimpul jikadibutuhkan). Padaimplementasidenganlinkedlist.Pohonkosongdiwakilidengannilaispesialnull. getLeft dan getRight dilakukan dengan mengakses variabel instans dari simpul, demikian hal nya dengan getCargo dan setCargo. Dalam hal ini kita belum mengimplementasikan getParent(andabisaberpikirbagaimanauntukmelakukanhal ini)
384
Setiapsimpulpadapohonmemilikiindeksyangunik.Indeksditempatkanpadasimpul menurutpolayangditentukan,denganaturansepertidibawah: 1. Anakkiridarisimpuldenganindeksimemilikiindeks2i. 2. Anakkanandarisimpuldenganindeksimemilikiindeks2i+1. 3. Orang tua dari simpul dengan indeks i memiliki indeks i/2 (pembulatan ke bawah). Menggunakan rumus ini, kita bisa mengimplementasikan getLeft, getRight, dan getParent dengan hanya menggunakan aritmatika; kita tidak harus menggunakan referensiuntuksemuahal!
BerikutiniimplementasisederhanadarigetCargodansetCargo. publicObjectgetCargo(inti){ returnarray[i]; } publicvoidsetCargo(inti,Objectobj){ array[i]=obj; } Metodeinitidakmelakukanpengecekanerrorapapun,jadijikaparametersalah,metode dapatmenghasilkaneksepsiArrayIndexOutOfBounds. ImplementasidarigetLeft,getRight,dangetParenthanyamenggunakanoperasi aritmatika: publicintgetLeft(inti){return2*i;} publicintgetRight(inti){return2*i+1;} publicintparent(inti){returni/2;} 386
Akhirnyakelaspohonmenggunakanarraytelahsiapdigunakan.Padakelaslain(klien), kitabisamenulis: ArrayTreetree=newArrayTree(); tree.setCargo(1,"cargoforroot"); Konstruktor membangun sebuah pohon kosong. Memanggil setCargo meletakkan kalimatcargoforrootkedalamsimpulakar. Untukmenambahanakpadasimpulakar: tree.setCargo(tree.getLeft(1),"cargoforleft"); tree.setCargo(tree.getRight(1),"cargoforright"); Padakelaspohonkitadapatmenyediakansebuahmetodeyangmencetakisidaripohon dalambentukpreorder. publicvoidprint(inti){ Objectcargo=tree.getCargo(i); if(cargo==null)return; System.out.println(cargo); print(getRight(i)); print(getLeft(i)); } Untukmemanggilmetodeini,kitaharusmelewatkanindeksakarsebagai parameter. tree.print(1); Keluarannyaadalah: cargoforroot cargoforleft cargoforright
387
Implementasi ini menyediakan operasi dasar yang mendefinisikan sebuah pohon. Seperti yang telah saya tunjukkan sebelumnya, implementasi pohon menggunakan linkedlistmenyediakanoperasiyangsamatetapidengansintaksyangberbeda.
Dalambeberapahal,implementasimenggunakanarraysedikitaneh.Padasuatusaatkita mengasumsikan bahwa muatan null menunjukkan simpul yang tidak ada, tetapi itu beratikitatidakdapatmeletakkanobjeknullpadapohonsebagaimuatan.
Masalah lain adalah subpohon tidak direpresentasikan sebagai objek; Mereka direpresentasikandenganindekspadaarray.Untukmelewatkansimpulpohonsebagai parameter,kitaharusmelewatkansebuahreferensikeobjekpohondanindekskearray. Akibatnyabeberapaoperasiyangmudahdilakukanpadaimplementasidenganlinked list, seperti mengganti keseluruhan subtree, lebih sulit dilakukan pada implementasi denganarray.
Heap adalah implementasi dari PriorityQueue ADT yang berdasarkan atas implementasi pohonmenggunakanarray.Yang akanlebihefisienjikadibandingkan denganimplementasilain.
Untukmembuktikanklaimini,akankitalakukandalambeberapalangkah.Pertama,kita akan membangun cara untuk membandingkan kinerja dari beberapa implementasi. Berikutnya,kitaakanmelihatimplementasiyangdilakukanheap.Danterakhirkitaakan 388
membandingkanimplementasiPriorityQueuemenggunakanheapdenganyanglainnya (arraydanlist)danmelihatmengapaimplementasiheapdianggaplebihefisien.
8.2AnalisisKinerja
Ketika kita membandingkan algoritma, kita harus memiliki cara untuk mengetahui kapansuatualgoritmalebihcepatdibandingkandenganyanglain,ataumenggunakan ruang yang lebih sedikit, atau menggunakan sumber daya lain yang lebih sedikit. Pertanyaaniniberatuntukdijawabsecaradetil,karenawaktudanruangpenyimpanan yangdigunakansuatualgoritmabergantungpadaimplementasidarialgoritmatersebut, masalahtertentuyangakandiselesaikan,danperangkatkerasdimanaprogramberjalan.
Tujuandaribabiniadalahuntukmencaricarauntukmengetahuikinerjayangtidak tergantungpadasemuahalitu,danhanyabergantungpadaalgoritmitusendiri.Untuk memulai,kitaakanfokuspadawaktueksekusi;selanjutnyakitaakanberbicaratentang sumberdayayanglain. Adapunmasalahmasalahyangkitahadapiadalah: 1. Pertama,kinerjaalgoritmabergantungpadaperangkatkerasdimanaiaberjalan, jadi kita tidak akan berbicara tentang waktu eksekusi dengan satuan mutlak sepertidetik.Sebagaigantinya,kitamenghitungoperasiabstrakyangdilakukan suatualgoritma. 2. Kedua,kinerjaseringbergantungpadamasalahtertentuyangsedangkitacoba untukmenyelesaikannyabeberapamasalahlebihmudahdibandingkandengan yang lain. Untuk membandingkan algoritma, kita akan fokus pada skenario terburukatauskenarioratarata(umum). 3. Ketiga,Kinerjabergantungpadaukuranmasalah(biasanya,tetapitidakselalu, banyak elemen dalam sebuah collection). Kita menyelesaikan masalah ini 389
denganmenganggapwaktueksekusisebagaifungsidaribesarukuranmasalah. 4. Kinerja bergantung pada implementasi detail sebuah algoritma seperti pengalokasianobjekdanpengeksekusianmetode.Kitatidakakanmengurusihal inikarenatidakterlauberpengaruhpadatingkatkompleksitassepertibanyak operasiabstrakmenambahukuranmasalah. Untuk membuat masalah proses lebih nyata, perhatikan dua algoritma pengurutanbilanganbulatyangtelahkitalihat.Yangpertamaadalah selectionsort, yangtelahkitalihatpadabagian12.3.Berikutinipseudocodedarialgoritmatersebut. selectionsort(array){ for(inti=0;i<array.length;i++){ //findthelowestitematortotherightofi //swaptheithitemandthelowestitem } } Untuk melakukan operasi yang dispesifikasikan pada pseudocode, kita menuliskan metodeyangbernamafindLowestdanswap.BerikutinipseudocodemetodefindLowest danswap:
390
//ifthejthitemislower,replacelowestwithj } returnlowest; }
Pilihanyangbaikadalahberapakalikitamembandingkanduaitem.Banyakpilihanlain yang akan menghasilkan hasil yang sama pada akhirnya, tetapi menggunakan pembandingan item akan mudah kita lakukan dan kita akan bisa membandingkan algoritmapengurutanapapundenganmudah.
Langkah berikutnya adalah mendefinisikan ukuran masalah. Pada kasus ini kita memilihukuranarray,yangakankitasebutn.Langkahterakhir,kitaakanmenurunkan sebuah fungsi yang memberitahu berapa banyak operasi abstrak (dalam kasus ini, perbandingan)yangharuskitalakukan,sebagaifungsidarin.
391
Swapmengkopibeberapareferensi,tetapitidakmelakukanpembandinganapapun,jadi kita mengabaikan waktu untuk mengeksekusi swap. findLowest dimulai pada i dan menjelajahiarray,membandingkansetiapitemdenganlowest.Banyakitemyangakan dibandingkanadalahsebesarni,sehinggajumlahtotalperbandinganadalahni1.
Selanjutnya kita akan melilhat berapa kali findLowest dipanggil serta nilai i nya. Terakhirkalidipanggil,ibernilain2sehinggajumlahperbandinganadalah1.Iterasi sebelumnya melakukan dua perbandingan dan demikian seterusnya. Selama iterasi pertama,ibernilai0danjumlahperbandinganadalahn1.
18.3AnalisisMergeSort
392
Duakolompertamapadatabelmemperlihatkanbanyakarraypadasetiaptingkatandan banyak elemen dalam setiap array. Kolom ketiga memperlihatkan berapa kali penggabungandilakukansetiaptingkatanrekursi.Kolomberikutnyamemperlihatkan banyakperbandingansetiappenggabungandilakukan.
Jika and melihat pada pseudocode (atau pada implementasi anda) tentang penggabungan,andapastimenyadarikasusterburuknyaadalahsebanyakm1.Dimana madalahbanyakelemenyangakandigabungkan.
Langkah berikutnyaadalahmengalikan banyakpenggabungan tiaptingkatan dengan banyakperbandingansetiappenggabungan.Hasilnyaadalahkerjatotaltiaptingkatan. Padatitikinikitamengambilkeuntungandaritrikkecil.Kitatahupadaakhirnyakita hanya tertarik pada pangkat depan dari hasil yang didapatkan, sehingga kita bisa
393
mengabaikan1padabagianperbandingantiappenggabungan.Jikakitamelakukannya, totalkerjatiaptingkatanhanyan.
Berikutnya kita perlu tahu jumah tingkatan sebagai fungsi dari n. Kita akan mulai denganarraydengannelemendanmembaginyadalamduabagiansampaimendapatkan 1 elemen tiap bagian. Hal ini sama dengan mulai dari 1 danmengalikan dengan 2 sampaimendapatkann.Dengankatalain,kitainginmengetahuiberapakalikitaharus mengalikan 2 sebelum kita mendapatkan n. Jawabannya adalah banyak tingkatan, l adalahlogaritmabasisduadarin.
Terakhir,kitamengalikantotalkerjatiaptingkatan,n,denganbanyaktingkatan,log 2n untukmendapatkannlog2n.
18.4Overhead
Pertamakitamengabaikansebagianbesaroperasipadaprogramdanmenghitunghanya pembandingan.Kemudiankitahanyaakanmelihatpadakinerjapadakasusterburuk. Ketika kita menerjemahkan hasil dari analisis ini, kita harus menyimpannya pada ingatan.Karenamergesortnlog2n,kitabisamenganggapnyalebihbaikdariselection sort,tetapiinitidakberatibahwamergesortselalulebihcepat.Inihanyaberartijikakita mengurutkanarrayyanglebihdanlebihbesar,mergesortakanmenang. Lama pengeksekusian sepenuhnya tergantung pada implementasi detail algoritma, termasuk pekerjaan tambahan, disamping pembandingan yang telah kita hitung. Pekerjaan tambahan ini kadang kadang disebut overhead. Ia tidak mempengaruhi analisiskinerja,tetapimempengaruhiwaktueksekusialgoritmatersebut.
394
Sebagai contoh, implementasi mergesort kita sebenarnya mengalokasikan subarray sebelum membuat pemanggilan secara rekursif. Dan kemudian membiarkan mereka ditangani oleh garbage collector setelah digabungkan. Lihat kembali pada diagram mergesort,kitabisamelihatjumlahtotalruangyangdialokasikansamadengannlog 2 n, dan jumlah objek total yang dialokasikan adalah 2n. Selalu benar bahwa implementasi buruk dari algoritma yang baik adalah lebih baik dibandingkan implementasibaikdarialgoritmayangburuk.
18.5ImplementasiPriorityQueue
Padabab16kitatelahmelihatsebuahimplementasidariPriorityQueueyangdibuat denganarray.Elemenpadaarraytidakterurut,sehinggamudahuntukmenambahkan elemen baru, tetapi akan lebih susah untuk menghapus elemen, karena kita harus mencariitemdenganprioritastertinggi.
Sebagaialternatifimplementasidibuatberdasarkam sortedlist. Padakasusiniketika kitamenambahitembarukitamenjelajahilistdanmeletakkanitembarupadatempat yangbenar.Implementasiinimenggunakankemampuandarilist,dimanaakanmudah menambah simpul baru pada pertengahan list. Begitu juga menghapus item dengan prioritastertinggi,dimanaiaakanselaluterdapatpadaawallist.
Analisiskinerjadarioperasiinicukupmudah.Menambahkanitempadaakhirarrayatau menghapussimpuldariawallistmenggunakanwaktuyangsamatanpamemperhatikan jumlah item yang ada pada list. Jadi kedua operasi ini menggunakan waktu yang konstan.
Setiapkalikitamenjelajahiarrayataulist,menggunakanoperasidenganwaktuyang 395
Jadiberapalamawaktuyangdigunakanuntukmenambahdankemudianmenghapusn itemdariPriorityQueue?Untukimplementasiarray,nmenggunakanwaktusebanding dengan n tetapi penghapusan menggunakan waktu lebih lama. Penghapusan yang pertamaharusmenjelajahisemuanelemen;keduaharusmenjelajahin1dandemikian seterusnya,sampaipenghapusanterakhir,yanghanyaharusmencaripada1elemen. Sehingga total waktu nya adalah 1+2+...+n, yang menghasilkan n2/2+n/2. Jadi total untukpenambahandanpenghapusanadalahjumlahfungsilineardanfungsikuadrat, yangkitabisatahuakanmenghasilkanfungsikuadrat.
Analisis pada implementasi list sama. Penambahan pertama tidak membutuhkan penjelajahan,tetapisetelahitukitaharusmenjelajahilistsetiapkalikitamenambah sebuahitembaru.Padaumumnyakitatidakmengetahuiberapabanyakelemenpadalist yang haruskitajelajahi,karenaiabergantungpadadatadandengancarabagaiman merekaditambahkan,tetapikitabisamengasumsikanrataratakitaharusmenjelajahi setengahdarilist.Sayangnyabahkanmenjelajahisetengahdarilistadalahoperasiyang linear.
Jadi, sekali lagi, untuk menambah dan menghapus n item membutuhkan waktu n 2. Sehingga berdasarkan analisis kita tidak bisa mengatakan implementasi mana yang lebihbaik;implementasiarraydanlistkeduanyamerupakanoperasikuadratik.
Jikakitamengimplementasikanpriorityqueuemenggunakanheap,kitabisamelakukan 396
penambahandanpenghapusandenganwaktu logn. Sehinggatotalwaktuuntuknitem adalah nlogn, yang lebih baik dari n2. Itulah mengapa pada awal bab ini, saya menyebutkanbahwaheapadalahimplementasiefisiendaripriorityqueue.
18.6DefinisiHeap
Heapadalahsalahsatujenispohon.Iamemilikiduasifatyangtidakselaludimilikioleh pohonlain: completeness:pohonkomplet,yangberartisimpulditambahkandariataske kirikekanan,tanpameninggalkansaturuangpun. heapness:Itempadapohondenganprioritastertinggiadapadapuncakpohon, begitu jugapadasetiapsubpohon. Keduasifatinimembutuhkansedikitpenjelasan.Gambarberikutmemperlihatkan jumlahpohonyangkompletdantidakkomplet. bawah,
18.7Penghapusanpadaheap
Mungkinkelihatanganjilkitaakanmenghapussesuatudariheapsebelummenambah apapun,tetapisayapikirpenghapusanlebihmudahuntukdijelaskan.Sekilas,kita mungkinberpikirmengapusitemdariheapadalahoperasiyangkonstan,karenaitem denganprioritastertinggiselaluberadapadaakar.Masalahnyaadalahsetiapkita menghapussimpulakar,kitaditinggalkansesuatuyangbukanlagiheap.Sebelumkita dapatmengembalikanhasilnya,kitaharusmempebaikisifatheap.Kitamenyebut operasiinireheapify. Situasiinidigambarkanpadagambarberikut:
398
Simpulakarmemilikiprioritasrdanduasubpohon,AdanB.nilaipadaakarsubpohon AadalahadannilaipadasubpohonBadalahb.
dalamheapsetelahrdihapusadalahaataub.Itulahmengapakitabisamemilihyang manayanglebihbesardanmenggantinyadengannilaipadaakar.
18.8PenambahanHeap
Menambahkansebuahitembarupadaheapadalahoperasiyangmiripdengan penghapusanheap,perbedaanyabahwakitatidakmenghamburkanelemendariatas 400
tetapikitamenghamburkanelemenkeatasdaribawahheap.
18.9KinerjaHeap
Untukpenambahandanpenghapusan,kitamenggunakanoperasidenganwaktu yangkonstanuntukpenambahandanpenghapusanyangsebenarnya,tetapikemudian kitaharusmelakukanreheapifypadapohon.Padasatukasuskitamulaidariakardan
401
nlog2n.
18.10Heapsort
Hasildaribagianyanglalubisamenjadiinspirasiuntukalgoritmapengurutan.Terdapat nelemen,kitamenambahkanmerekakedalamHeapkemudianmenghapusnya.Karena sifatheap,merekaakankeluardalamkeadaanterurut.Kitatelahmemperlihatkan algoritmaini,yangdisebutheapsort,iamenggunakanwaktusebandingdengannlog2n, yanglebihbaikdariselectionsortdansamadenganmergesort.
KompleksitaskadangkadangditulisdalamnotasibigO.misalnyaO(n^2),diucapkan denganohofensquaredadalahkumpulanfungsiyangberkembangtidaklebihcepat darin^2untuknilainyangbesar.UntukmengatakansebuahalgoritmaadalahO(n^2) samadenganalgoritmatersebutkuadratik.Untukkasuskompleksitaslainyangtelah kitalihat,denganurutankinerjamenurun,adalah O(1)constanttime O(logn)logarithmic O(n)linear O(nlogn)enlogen O(n2)quadratic O(2n)exponential 403
18.11DaftarKataKata
selectionsort:Algoritmapengurutansederhanapadabab12.3. mergesort:Algoritmapengurutanyanglebihbaikdaribab12.6. heapsort:Algoritmapengurutanyanglain. kompleksitas:kumpulanalgoritmayangkinerjanya(biasanyawaktueksekusi) memilikiorderofgrowthyangsama. orderofgrowth:Kumpulanfungsidenganpangkatawalyangsama,dankarena itusamadalamsifatkualitatifuntuknilainyangbesar. overhead:waktuatausumberdayatambahanyangdikonsumsiolehsebuah programdalammelakukansuatuoperasiselaindarioperasiabstrakyang diperhitungkanpadaanalisiskinerja.
404
18.12Latihan
latihan18.3 a) GambarHeapyangdirepresentasikanpadaarraydibawahini.
b) Perlihatkansusunanarrayketika68ditambahkankedalamheap. Latihan18.4 Asumsikanterdapatnelemendalamheap.Untukmencarinilaitengahdarielemen,kita dapatmenghapusn/21elemendanmengembalikannilaielemenken/2.Kemudiankita harusmeletakkann/2elemenkembalikedalamheap.Berapaorderofgrowthdari algoritmaini? Latihan18.5 Berapakaliloopdibawahinidieksekusi?Kemukakanjawabanmusebagaifungsidari n: while(n>1){ n=n/2; } Latihan18.6 Berapabanyakpemanggilanrekursifyangdilakukanzippo?Kemukakanjawabanmu sebagaifungsidarixataunataukeduanya. publicstaticdoublezippo(doublex,intn){ if(n==0)return1.0; returnx*zippo(x,n1); }
405
406
Meskipunarraydapatberisitipeapapun,indeksarrayharusbertipeinteger. KitatidakdapatmisalnyamenggunakanStringuntukdigunakansebagaiindeks.
407
ContohumumdaristrukturdataMapadalahkamus,yangmemetakankatakata(kunci) padadefinisinya(nilai).KarenahaliniMapjugakadangdisebutkamus.
19.2MapADT
19.3HashMapbuiltin
JavamenyediakanimplementasidariMapADTpadapaketjava.util.HashMap. SelanjutnyapadababinikitaakanlihatmengapadisebutHashMap
408
KitaakanmembuatkelasbaruyaituWordCountyangakanmembangunMapdan mencetakisinya.SetiapWordCountberisiHashMapsebagaivariabelinstance.
publicclassWordCount{ HashMapMap;
publicWordCount(){ Map=newHashMap(); } }
publicvoidprocessLine(Strings){
409
410
BerikutinicarauntukmenggunakankeySetuntukmencetakisidariHashMap: //catatanagarkodebisafungsionalandaharusmenambahkanbarisimportjava.util.* sebelum//deklarasikelas publicvoidprint(){ Setset=Map.keySet(); Iteratorit=set.iterator(); while(it.hasNext()){ Stringkunci=(String)it.next(); integervalue=(integer)Map.get(kunci); System.out.println("{"+kunci+","+value+"}"); } }
Berikutinicarauntukmenghitungkatakatapadasebuahkalimat:
411
Keluarannyaadalah {you,1} {round,5} {right,3} {me,1} {like,1} {baby,2} {spin,1} {record,1} {a,1}
ElemenelemenpadaIteratortidakdiurutkanberdasarkanaturantertentu.Satusatunya jaminanadalahsemuakuncipadaMapakanmuncul.
BerikutinikodekelasWordCountsecarakeseluruhan:
importjava.util.*;
publicvoidprocessLine(Strings){ StringTokenizerst=newStringTokenizer(s,",.");
412
publicstaticvoidmain(String[]args){ WordCountwc=newWordCount();
413
19.4ImplementasiDenganVector
CarayangmudahuntukmengimplementasikanMapADTadalahmenggunakanentri denganstrukturdataVector,dimanasetiapentriadalahsebuahobjekyangberisisebuah kuncidansebuahnilai.DefinisikelasdariEntrysepertidibawahini:
LaluimplementasidariMapsepertidibawahini:
414
KemudianuntukmelihatsebuahkuncipadaMapkitaharusmenjelajahiVectordan mencarisebuahEntrydengankunciyangsesuai.
415
Sekarangkitatelahmemilikimetodeget,kitabisamenulisversidariputyanglebih lengkap.JikatelahterdapatentripadaMapdengankunciyangdiberikan,putakan memperbaharuinya(memberinyanilaiyangbaru),danmengembalikannilaiyanglama( ataunulljikabelumada).iniadalahimplementasimetodeyangmenyediakanfiturini: publicObjectput(Objectkunci,Objectvalue){ Objectresult=get(kunci); if(result==null){ Entryentry=newEntry(kunci,value); entries.add(entry); }else{ update(kunci,value);
416
417
ImplementasilengkapMapmenggunakanVector:
importjava.util.*; publicclassMyMap{ Vectorentries;
publicMyMap(){ entries=newVector(); }
418
update(kunci,value); } returnresult; }
publicbooleancontainsKey(Objectkunci){ if(get(kunci)==null)
419
ContohkelasWordCountmenggunakanimplementasiMapdenganVector
importjava.util.*;
420
421
} }
19.5KelasAbstrakList
Paketjava.utilmendefinisikansebuahkelasabstrakyangmenspesifikasikanhimpunan operasiyangsebuahkelasharusmengimplementasikanagardapatdisebutList,Initidak berartibahwasetiapkelasyangmengimplementasikanListharusmerupkanstruktur datalinkedlist.
TidakanehbahwakelasbawaanLinkedListadalahimplementasidariList.Danyang mengejutkankelasVectorjugamerupakanimplementasidarikelasList.
422
bekerjadenganbaik.
19.6ImplementasidenganHashMap
AlasanimplementasibawaanMapADTdisebutHashMapkarenaiamenggunakan sebuahimplementasiMapyangefisienmenggunakantabelhash. UntuklebihmemahamiimplementasiHashMapdanmengapaiadianggapefisien.Kita akanmemulaidenganmenganalisaperformadariimplementasiList.
423
19.7FungsiHash
Danitulahdimanafungsihashbisadipergunakan.Kitamembutuhkancarauntuk melihatsebuahkuncidantahutanpamencari,padaListmanaiaberada.Kitaakan mengasumsikanbahwaListadadidalamarray(atauVector)jadikitabisa mereferensinyadengandenganindex.
424
tetapiadabanyakbilanganinteger(bulat)yangtidakberadaantara0dan7,padahal indeksyanglegalharusberadaantara0dan7.
Operatormodulusmenyediakancarayangsederhanadanefisienuntukmemetakan semuabilanganbulat(integer)antara0dan7.Perhitungan kunci.intValue%8 dijaminmenghasilkannilaidalamrentang7sampai7(termasukkeduanya).Jikaanda mengambilnilaiabsolut(menggunakanMath.abs)andaakanmendapatkanindeksyang sah. Untuktipeyanglain,dapatditerapkancarayangsama.Misalnyauntukmengkonversi variabelbertipeCharactermenjadibilanganbulat,kitadapatmenggunakanmetode bawaanCharacter.getNumericValuedanuntuktipeDoubledapatdigunakanmetode intValue.
425
Sebagailatihan,tulissebuahmetodeyangmenghitungshiftedsumnilaibilangansemua karakterpadaStringmenggunakanpengali16.
Terlepasdaribagaimanacaramenghasilkanhashcode,langkahterakhiradalah menggunakanmodulusdanfungsinilaiabsolutuntukmemetakanhashcodepada
426
rentangindeksyanglegal.
19.8MengubahUkuranHashMap.
Sebuahhashtableberisisebuaharray(atauVector)yangelemennyamerupakansebuah List.DimanasetiapListberisijumlahentriyangkecil.Untukmenambahentribaru padaMap,kitamenghitunghashcodepadakunciyangbarudanmenambahentri tersebutpadaListyangsesuai. Untukmencarisebuahkunci,kitamenghitunghashlagidanmencarinyapadaListyang sesuai.JikapanjangListterbatasmakawaktupencarianjugaterbatas.
Bahkandengankeseimbanganyangsempurna,rataratapanjangListberkembangsecara lineardenganjumlahentri.Dankitaharusmeletakkantitikhentipadasaatitu.
SolusinyaadalahdenganmengikutirataratajumlahentriuntuksetiapList,yangdisebut loadfactor.Jikaloadfactorterlalutinggikitaharusmengubahukuranhashtable.
427
berbedauntukoperatormodulus.
19.9Kinerjadaripengubahanukuran
Beberapaoperasiputmembutuhkanwaktuyanglebihlamadibandingkandenganyang lain,marikitagambarkanwakturataratadalamoperasiput.Rataratadilambangkan dengancyaituwaktukonstanuntukputyangsederhana.Ditambahdenganp, prosentasewaktusebelumdilakukanpengubahanukuran,dikalidengankn,makabiaya untukmengubahukuranadalah. t(n)=c+pkn (19.1) Kitatidaktahumelambangkanapacdank,tetapikitabisamenggambarkanapakahp itu.BayangkankitabarusajamengubahukuranhashMapdenganmemperbesardua kaliukurannya.Jikaterdapatnentrilalukitadapatmenambahkantambahannentri sebelumkitaharusmengubahukrannyalagi.Jadipersentasiwaktusebelumharus
428
dilakukanpengubahanukurankembaliadalah1/n.
19.10DaftarKata
map:SebuahADT(AbstractDataType)yangmendefinisikanoperasipadakumpulan entri. entri:Elemenpadamapyangberisisebuahkuncidansebuahnilai. kunci:Indeks,dapatberupaobjekapapun,digunakanuntukmencarinilaidalammap. value:Elemen,dapatberupaobjekapapun,disimandalammap. dictionary:namalaindarimap. arrayassosiatif:namalaindaridictionary. hashmap:Sebuahimplementasiefisiendarimap. fungsihash:fungsiyangmemetakannilaipadatipetertentukepadabilanganbulat. hashcode:bilanganbulatyangberhubungandengansebuahnilai. shiftedsum:fungsihashsederhanayangseringdigunakanuntukobjekmajemuk sepertiString loadfactor:banyakentridalamhashmapdibagidenganbanyakListdalamhashmap; sebagaicontohrataratabanyakentritiapList.
429
19.11Latihan
latihan19.2 a. Hitungshiftsumdaribilanganbilangan1,2,3,4,5,6menggunakanpengali10 b. Hitungshiftsumdaribilanganbilangan11,12,13,14,15,16menggunakan pengali100 c. Hitungshiftsumdaribilanganbilangan11,12,13,14,15,16menggunakan pengali10
Selanjutnya,andamembuatsebuaharraydariobjekhariulangtahunyangberisisatu objekuntuktiaporangpadapesta. a. Tulissebuahmetodeequalsuntukhariulangtahunsehinggahariulangtahun denganbulandanhariyangsamaadalahsama(equal). b. TulissebuahmetodebernamahasDuplicateyangmengambilsebuaharray objekhariulangtahundanmengembalikantruejikaterdapatduaataulebihorang yangmemilikihariulangtahunsama.Algoritmaandaharushanyamenjelajahi arrayobjekhariulangtahunsekali. c. TulissebuahmetodeyangbernamarandomBirthdaysdenganparameterinteger ndanmengembalikanarraydengannobjekhariulangtahunyangatributatribut nyadiisisecaraacak.Agarlebihsederhana,andabisamengganggapsemua bulanadalah30hari. d. Bangkitkan100arrayacak,masingmasingarray10objekhariulangtahun,dan lihatberapabanyakarrayyangberisihariulangtahunyangsama. e. Jikaterdapat20orangpadapesta,berapakemungkinansatuataulebihpeserta pestamemilikihariulangtahunyangsama.
431
BuatimplementasiSetmenggunakanHashMap
Latihan19.11 Paketjava.utilmenyediakanduaimplementasiMap,yaituHashMapdanTreeMap, HashMapdibangundenganmeniruhashtablesepertiyangdijelaskanpadababini. TreeMapdibuatberdasarkanredblacktree,yangmiripdenganpohonpencarianpada latihan17.6. Meskipunkeduaimplementasiinimeyediakanantarmukayangsama,kita mengharapkannyamencapaikinerjayangberbeda.Sejalandenganbanyakentrin bertambah,kitaberharapadddancontainsmenggunakanwaktukonstanuntuk implementasihashtable.Danwaktuyanglogaritmikuntukimplementasidengan pohon.
433
434
Langkahterakhir,kitaakanmenjelajahiphonhuffmandanmemanguntabel kode,yangberisirangkaiantitikdangarisuntuksetiappohon.
20.2Tabelfrekuensi
Karenatujuannyaadalahmemberikankodependekpadakatayangumum,kitaharus tahuberapakalisetiaphurufmuncul.PadaceritapendekEdgarAllenPoeTheGold Bug,salahsatukaraktermenggunakanfrekuensihurufuntukmemecahkanchiper.Dia menjelaskan
Sekarangdalambahasainggris,hurufyangpalingseringmunculadalahe, setelahituaoidhnrstuycfglmwbkpqxz.
JadimisipertamakitaadalahmelihatapakahPoebenar.
435
436
20.3PohonHuffman
Langkahberikutnyaadalahmembangunpohonhuffman.Setiapsimpulpadapohon berisisebuahhurufdanfrekuensinya,sertapenunjukkesimpulkiridankanan.Untuk membangunpohonHuffman,kitamulaidenganmembuathimpunanpohontunggal, satudarisetiapentripadatabelfrekuensi.Lalukitamembangunpohondaribawahke atas,dimulaidarihurufdenganfrekuensiterendahdansecaraberulangmenggabungkan subphonsampaimendapatkanpohontunggalyangberisisemuahuruf.
Sebagaicontohkitaakanmenggunakanteksdibawahuntukmembentukpohon Huffman.
Teksdiatasmenghasilkantebelfrekuensi: e a t s n r d 40 32 24 22 20 19 13
Jadisetelahlangkah1,PriorityQueueakanterlihatseperti:
Sekarangulangilangkahsebelumnya,denganmenggabungkansdann:
Setelahiterasiberikutnya,kitamemilikikumpulanpohonsepertidibawah,Sebagai 438
informasikumpulanpohonbiasadisebuthutan.
Setelahduaiterasilagi,hanyaakanadatigapohonyangtertinggal:
IniadalahpohonHuffmanuntuktekscontoh.Sebenarnya,iabukansatusatunya karenasetiapkalikitamenggabungkanduapohon,kitamemilihyangmanamenjadi simpulkanandanyangmanadikiri,danketikaadapohonyangsamapada PriorityQueue,kitamemilihtergantungselera.Jadiakanadabanyakkemungkinan pohonpadacontohdiatas. JadibagaimanakitamengambilsebuahkodedaripohonHuffman?Kodeuntuk setiaphurufdihitungdenganmenelusurijalandariakarpohonsampaidaunyangberisi hurufyangdimaksud.Misalnyajalandariakarsampaisadalahkirikanankiri.Jikakita menggantikiridengan.dankanandengankitamendapatkantabelkodedibawah: e a . 439
t s n r d
.. .. . .... ...
20.4Metodesuper
SalahsatucarauntukmengimplementasikanpohonHuffmanadalahdengan menurunkannyadarikelasPairdarilatihan20.13 publicclassHuffTreeextendsPairimplementsComparable{ HuffTreeleft,right; publicHuffTree(intfreq,Stringletter, HuffTreeleft,HuffTreeright){ 440
441
KetikacompareTodipanggilpadaHuffTree,iaakanmemanggilversicompareTopada kelasorangtua,danmenegatifkanhasilnya.Sehinggaurutanprioritasmenjaditerbalik.
442
padabagian20.3.
20.5PemecahanKode
Ketikakitamenerimapesanyangdikodekan,kitamenggunakanpohonHuffmanuntuk memecahkodenya.Dibawahinialgoritmauntukmelakukanhaltersebut: 1. MulaidariakarpohonHuffman 2. Jikasimbolberikutnyaadalah.,makaberlanjutkeanaksebelahkiri,jikatidak makaberlanjutkeanaksebelahkanan. 3. Jikaandaberadapadasimpuldaun.Ambilhurufnyadantambahkanpadahasil. Lalukembalikeakar. 4. Kelangkah2.
Perhatikanketikaandamulaimemecahkankode,andatidakdapatmengetahuiberapa 443
banyakhurufpadakodeatauberadadimanabatasbatashurufnya.
20.6Pengkodean
Biasanya,pengkodeanlebihsulitdibandingkandenganpemecahankode,karenauntuk suatuhurufkitaharusmencarisimpuldaunpadapohonyangberisihuruftersebutdan dilanjutkandenganmenggambarkanlintasandariakarsampaisimpultersebut.
Prosesiniakanlebihefisienjikakitamenjelajahipohonsekali,memprosessemuakode, danmembangunMapdarihurufkekode(hurufsebagaikuncidankodesebagainilai).
Latihan20.18 1. TulisdefinisikelasdariCodeTab,yangditurunkandariHashMap. 2. PadadefinisiCodeTab,tulismetoderekursifyangbernamagetCodes.Metode inimenjelajahipohonHuffman.Ketikaiamencapaisimpuldaun,iaakan mencetakhurufpadasimpuldankodeyangmenyimbolkanlintasandariakarke simpultersebut. 3. TuliskonstruktoruntukCodeTabyangmengambilHuffTreesebagaiparameter danmengeksekusigetCodesuntukmembanguntabelkode. 4. PadakelasHuffman,tulismetodeencodeyangmenjelajahisebuahkalimat, mencarisetiapkarakterpadatabelkodedanmengembalikankalimatyangtelah dikodekan.Ujimetodeinidenganmelewatkanhasilnyapadadecodedanlihat apakahiamengembalikankalimatyangasli.
20.7DaftarKata
hutan:kumpulanpohon superclass:namalaindarikelasorangtua subclass:namalaindarikelasanak. super:katakunciyangdigunakanuntukmemanggilmetodeyangditutupipada superclass.
445
LampiranForeachdanGenerik Generik
GenerikadalahkemampuanbarupadaJava1.5yangdigunakandalampembentukan Collection(List,Set,dll).ParapenggunaJavatentumengetahuisalahsatukelemahan penggunaanCollectionsebelumnyaadalahadanyakeharusanuntukmengcastingObjek saatdiambildariCollection.Prosespengcastinganinicukupberbahayakarena pengecekanapakahCastingbisadilakukandenganbenardilakukansaatruntime, sehinggaberisikomenghasilkanRuntimeException.
Contohdeklarasidengangenerik:
List<Integer>l=newArrayList<Integer>(); Set<Double>s=newHashSet<Double>();
446
importjava.util.*;
importjava.util.*;
447
Foreach
ForeachadalahsyntaxbaruJavayangjugabarudiperkenalkansemenjakJava1.5. Foreachsangatbergunaketikaandainginmenjelajahisemuaelemendalamsatu Collectionatauarray.Syntaxbaruinidikeluarkankarenasebelumnyauntuk melakukanpenjelajahanpadaCollectionmenggunakanmetodeIteratoryangcukup rumitdalampenggunaannya.
importjava.util.*; classTest{ publicstaticvoidmain(String[]args){ List<Integer>l=newArrayList<Integer>(); l.add(1); l.add(2); Iteratoriter=l.iterator(); while(iter.hasNext()){ Objecti=iter.next(); System.out.println(i); } } }
448
Secaraumumsyntaxforeachadalah:
for(<tipedatadalamCollectionatayarray><namavariabel>:<Collectionatauarrayyangakan dijelajahi>) <statemen>
Kodediatassamasekalitidakakanmengubahisiarrayarray.Sehinggasaatanda mencetaknyayangtampiltetaparrayyangasli.
450
DaftarKata
Collection:TipeumumStrukturdataJava,strukturdataList,Set,Map,danlainlain diturunkan darikelasini.Biasanyadigunakanuntukmengacupadakeseluruhan
451
JawabanLatihan Bab2
Latihan2.1 classDate{
publicstaticvoidmain(String[]args){ Stringhari; hari="Sabtu"; inttanggal; tanggal=16; Stringbulan; bulan="September"; inttahun; tahun=2006; System.out.println("FormatAmerika:"); System.out.println(hari+","+bulan+""+tanggal+","+tahun); System.out.println("FormatEropa:"); System.out.println(hari+""+tanggal+""+bulan+","+tahun); } }
452
intjam,menit,detik; jam=6; menit=26; detik=20; intdetik_saat_ini; detik_saat_ini=6*3600+26*60+20; System.out.println("Detiksaatinisejaktengahmalamadalah "+detik_saat_ini+"detik"); intjumlah_detik_dalam_sehari; jumlah_detik_dalam_sehari=24*3600; intsisa_detik=jumlah_detik_dalam_seharidetik_saat_ini; System.out.println("Sisadetiksaatini="+sisa_detik+"detik"); intprosentase_sisa_detik; prosentase_sisa_detik=sisa_detik*100/jumlah_detik_dalam_sehari; System.out.println("Prosentasesisadetiksaatini= "+prosentase_sisa_detik+"%"); } }
Bab3
Latihan3.1
453
Hour
11
main
Minute
59
Hour
11
printTime
Minute
59
publicstaticvoidmain(String[]args){ zool(11,"chicken","gajahmada"); } }
454
Latihan3.4 classDate{
publicstaticvoidmain(String[]args){ Stringhari; hari="Sabtu"; inttanggal; tanggal=16; Stringbulan; bulan="September"; inttahun; tahun=2006; System.out.println("FormatAmerika:"); printAmerican(hari,tanggal,bulan,tahun); System.out.println("FormatEropa:"); printEuropean(hari,tanggal,bulan,tahun); 455
} }
publicstaticvoidyikes(doublex){ multadd(x,Math.exp(x),+(Math.sqrt(1Math.exp(x)))); } }
Bab4
Latihan4.1 456
n n
Latihan4.2 publicstaticbooleanisTriangle(inta,intb,intc){ if(a>(b+c)) returnfalse; elseif(b>(a+c)) returnfalse; elseif(c>(a+b)) returnfalse; else returntrue; }
Bab6
457
Latihan6.1.a
i 10 5 6 3 4 2 1 2 1
n 10 10 10 10 10 10 10 10 10
458
inti=0; intcount=0;
while(i<len){ charc=s.charAt(i);
459
publicstaticintfooMethod(Strings,charkar1,charkar2){ intlen=s.length();
inti=0; intcount=0;
while(i<len){ charc=s.charAt(i);
460
461
} returnresult; }
c) publicstaticvoidcheck(doublex){ System.out.println(x+"\t"+Math.exp(x)+"\t"+myexp(x,100)); }
Bab7
LatihanTambahan publicstaticvoidprintBackward(Strings){ intindex=s.length()1; while(index>=0){ charletter=s.charAt(index); System.out.print(letter); index=index1; } System.out.println(); }
Latihan7.3 Programtidakakanmencetakbilangansecaraterbaliktetapiakanmencetak
465
penjumlahandigitpertamadandigitterakhir.Programharusnyasepertiberikut: intnumber=17; intlastDigit=number%10; intfirstDigit=number/10; System.out.println(lastDigit++firstDigit); Latihan7.4 Programakanmencetakmengkonversibilanganbasis10menjadibilanganbiner. Latihan7.5 classPalindrome{ publicstaticcharfirst(Stringstr){ returnstr.charAt(0); } publicstaticcharlast(Stringstr){ returnstr.charAt(str.length()1); } publicstaticStringmiddle(Stringstr){ intindeks=1; Stringresult=""; while(indeks<str.length()1){ result+=str.charAt(indeks); indeks++; } returnresult; } publicstaticbooleanisPalindrome(Stringstr){ if(str.length()<=1) returntrue; if(first(str)==last(str)){ Stringmiddle=middle(str); returnisPalindrome(middle); }else{ returnfalse; } 466
} publicstaticbooleanisPalindromeIter(Stringstr){ if(str.length()<=1) returntrue; intlength=str.length(); for(inti=0;i<length/2;i++){ if(str.charAt(i)!=str.charAt(length1i)) returnfalse; } returntrue; } } Latihan7.6 publicstaticbooleanisAbcedarian(Stringstr){ char[]charArr=str.toLowerCase().toCharArray(); for(inti=1;i<charArr.length;i++){ if(charArr[i]<=charArr[i1]) returnfalse; } returntrue; }
467
} returntrue; }
468
publicstaticintcompareName(Stringname1,Stringname2){ name1=convertName(name1.toLowerCase()); name2=convertName(name2.toLowerCase()); for(inti=0;i<Math.min(name1.length(),name2.length());i++){ if(name1.charAt(i)==name2.charAt(i)) continue; elseif(name1.charAt(i)>name2.charAt(i)) return1; else return1; } if(name2.length()>name1.length()) return1; elseif(name2.length()<name1.length()) return1;
469
if(Character.isLowerCase(c)){ if(addition>26||addition<26) addition%=26; intascii=(char)c; ascii+=addition; if(ascii>122) ascii=96+(ascii122); elseif(ascii<97) ascii=122+(96ascii); return(char)ascii;
} returnc; }
Bab8
latihan8.1 b) 5 1 2
Latihan8.2
Latihan8.4
472
Bab9
intvalue; charletter;
publicstaticvoidprint(Tilet){ System.out.println("letter"+t.letter+"hasvalue"+t.value); }
publicDate(){}
474
publicRational(inta,intb){ 475
numerator=a; denominator=b; }
publicstaticvoidprintRational(Rationalr){ System.out.println(r.numerator+"/"+r.denominator); }
publicvoidnegate(){ numerator=numerator; }
publicstaticdoubletoDouble(Rationalr){ return(double)r.numerator/r.denominator; }
publicstaticRationaladd(Rationalr1,Rationalr2){ 477
publicstaticvoidmain(String[]args){ Rationalr=newRational(36,20); Rational.printRational(r); r.negate(); Rational.printRational(r); r.invert(); Rational.printRational(r); System.out.println(Rational.toDouble(r)); r=Rational.reduce(newRational(36,20)); Rational.printRational(r);
Bab10
Latihan10.1dan10.2
returnlow+(Math.random()*(high1)); }
publicstaticintrandomInt(intlow,inthigh){ returnlow+(int)(Math.random()*(high1)); }
latihan10.5 publicstaticintfindInRange(int[]arr,intbil,intlow,inthigh){ if(low==high){ if(arr[low]==bil) returnlow; else return1; } intmid=(low+high)/2; intresult=findInRange(arr,bil,low,mid); if(result==1){ intresult1=findInRange(arr,bil,mid+1,high); returnresult1; }else returnresult;
} 480
Latihan10.6 publicstaticint[]arrayHist(int[]scores){ int[]counts=newint[11]; for(inti=0;i<scores.length;i++){ if(scores[i]<=0) counts[0]++; elseif(scores[i]>=10) counts[10]++; else counts[scores[i]]++; } returncounts; }
481
Latihan10.9 classArray{ publicstaticintmaxInRange(int[]arr,intlow,inthigh){ if(low==high) returnarr[low]; if(low==high1) returnMath.max(arr[low],arr[high]); intmid=(low+high)/2; return Math.max(maxInRange(arr,mid+1,high),maxInRange(arr,low,mid));
publicstaticintmax(int[]arr){ returnmaxInRange(arr,0,arr.length1); }
publicstaticint[]letterHist(Stringkal){ int[]counts=newint[27]; char[]kar=kal.toCharArray(); for(inti=0;i<kar.length;i++){ if(kar[i]==''){ counts[26]++; continue; } kar[i]=Character.toLowerCase(kar[i]); counts[kar[i]97]++; } returncounts; }
publicstaticvoidmain(String[]args){ System.out.println(isDoubloon("alalsxxsx")); } }
latihan10.13 classScrabble{ publicstaticbooleantestWord(Stringtiles,Stringwords){ int[]tilesCount=LetterHist.letterHist(tiles); int[]wordCount=LetterHist.letterHist(words); for(inti=0;i<wordCount.length;i++){ if(wordCount[i]<=tilesCount[i]) continue; else returnfalse;
} returntrue; } 486
publicstaticvoidmain(String[]args){ System.out.println(testWordModif("qijbo","jjib")); } }
487
Bab11
classCardUtility{ publicstaticCard[]buildDeck(){ Carddeck[]=newCard[52]; intindex=0; for(intsuit=0;suit<=3;suit++){ for(intrank=1;rank<=13;rank++){ deck[index]=newCard(suit,rank); index++; } } returndeck; }
488
publicstaticintStringToSuit(Stringstr){ if(str.equals("Clubs")) return0; if(str.equals("Diamonds")) return1; if(str.equals("Hearts")) return2; if(str.equals("Spades")) return3; else return99; }
} }
publicstaticvoidmain(String[]args){ parseCard("1ofDiamonds"); } }
publicCard(){ 491
suit=0; rank=0; }
publicintgetSuit(){ returnsuit; }
publicintgetRank(){ returnrank; } }
Bab12
latihan12.1 classSearch{ publicstaticintfindBisect(Deckd,Cardc,intlow,inthigh){ System.out.println(low+""+high); if(high<low) return1; 492
intmid=(high+low)/2; intcomp=d.cards[mid].compareCard(c); if(comp==0) returnmid; elseif(comp>0){ Decksub=Deck.subDeck(d,low,mid1); returnfindBisect(sub,c,low,mid1); }else{ Decksub=Deck.subDeck(d,mid+1,high); returnfindBisect(sub,c,mid+1,high); } }
latihan12.5 publicclassPoker{ publicDeck[]getHands(){ Deckd=newDeck(); Deck.shuffleDeck(d); Deck[]arr=newDeck[4]; arr[0]=Deck.subdeck(d,0,4); arr[1]=Deck.subdeck(d,5,9); arr[2]=Deck.subdeck(d,10,14); arr[3]=Deck.subdeck(d,15,19); 493
returnarr;
publicstaticbooleanisFlush(Deckd){ returnCardUtility.isFlush(d.cards); }
returnfalse; }
continue; }
returnfalse; }
returnfalse; }
496
publicstaticbooleanisStraight(Deckd){ Card[]cards=d.cards; Card[]temp=newCard[cards.length]; for(inti=0;i<cards.length;i++) temp[i]=cards[i]; for(inti=0;i<temp.length;i++){ intindex=getLowestCard(temp,i,temp.length1); Deck.swapCards(temp,i,index); if(i>=1){ if(temp[i].getRank()!=temp[i1].getRank()+1) returnfalse; } } returntrue; }
publicstaticbooleanisFullHouse(Deckd){ Card[]cards=d.cards; int[]counter=newint[13]; for(inti=0;i<cards.length;i++){ counter[cards[i].getRank()]++; } //returntrueifthree&two=true booleanthree=false; booleantwo=false; for(inti=0;i<counter.length;i++){ 497
returnfalse; }
returnmin; }
} 498
publicDeck(intn){ cards=newCard[n]; }
publicstaticDeckmerge(Deckd1,Deckd2){
for(intk=0;k<result.cards.length;k++){
} returnresult; }
502
publicstaticDeckmergeSort1(Deckdeck){
intmid=(deck.cards.length1)/2;
503
publicstaticvoidmain(String[]args){ Deckd=newDeck(5); Card[]c=newCard[5]; c[0]=newCard(3,5); c[1]=newCard(0,5); c[2]=newCard(0,4); c[3]=newCard(4,4); c[4]=newCard(1,5); d.cards=c; Deckd1=mergeSort2(d); for(inti=0;i<d1.cards.length;i++){ System.out.println(d1.cards[i].getSuit()+" "+d1.cards[i].getRank()); } }
Bab13
latihan13.2
publicvoidprintComplex(){ System.out.println(real+"+"+imag+"i"); }
publicvoidconjugate(){ 505
imag=imag; }
506
Complexy=newComplex(3,4);
System.out.println(y.abs());
x.add(y); x.printComplex(); } }
Bab14
latihan14.1 publicclassIntList{ intlength; Nodehead;
Nodesecond=list.next;
//makethefirstnoderefertothethird first.next=second.next;
publicvoidadd(intindex,intcargo){ if(index>=1&&index<=length){ NodenewNode=newNode(); newNode.cargo=cargo; inti=1; Nodelist=head; while(i<index){ list=list.next; i++; } newNode.next=list.next; list.next=newNode; length++; } }
publicvoidreverse(){ Nodelist=head; Nodetemp=list.next; list.next=null; Nodeprev=list; while(temp!=null){ list=temp; temp=list.next; list.next=prev; prev=list; } head=list; }
510
publicbooleancheckLength(){ if(head==null) returnfalse; Nodenode=head; intpanjang=0; while(node!=null&&node.next!=node){ panjang++; node=node.next; } System.out.println(panjang); System.out.println(length); if(panjang==length) returntrue; else returnfalse; }
511
System.out.print("(");
//startatthebeginningofthelist node=head;
System.out.println(")"); }
publicvoidprintBackward(){ System.out.print("(");
if(head!=null){ 512
publicstaticvoidmain(String[]args){
//createanemptylist IntListlist=newIntList();
Nodenode2=newNode(); node2.cargo=2;
list.head=node1; list.length=3;
list.print();
IntListlist2=newIntList();
Nodenode5=newNode(); node5.cargo=5;
Nodenode6=newNode(); node6.cargo=6;
list2.head=node4; list2.length=3;
515
} }
publicstaticvoidprintBackward(Nodelist){ if(list==null)return;
Nodehead=list; Nodetail=list.next;
printBackward(tail); System.out.print(head+","); }
System.out.println(); } }
//Thisprogramispartof"Howtothinklikeacomputerscientist," //byAllenB.Downey,whichisavailablefromthinkAPjava.com
//ThisprogramislicensedundertheGNUFreeSoftwareLicense, 517
//thetermsofwhichareavailablefromwww.gnu.org
Nodenode2=newNode(); node2.cargo=2;
Nodenode3=newNode(); node3.cargo=1;
list.head=node1; list.length=3;
IntListlist2=newIntList();
Nodenode4=newNode(); 518
node4.cargo=2;
Nodenode5=newNode(); node5.cargo=6;
Nodenode6=newNode(); node6.cargo=1;
list2.head=node4; list2.length=3;
System.out.println("hasil="+compare(list,list2));
Nodenode1=list1.head; Nodenode2=list2.head; intresult=0; while(node1!=null){ if(node1.cargo>node2.cargo) result=1; elseif(node1.cargo<node2.cargo) result=1; elseif(node1.cargo==node2.cargo) result=result; node1=node1.next; node2=node2.next; } returnresult; } } }
Bab15
15.1 importjava.util.*;
classLatihan15_1{
publicstaticvoidreverse(int[]arr){ 520
//makethefirstnoderefertothethird first.next=second.next;
System.out.print("(");
System.out.println(")"); }
publicvoidprintBackward(){ System.out.print("(");
publicvoidaddFirst(Objectcargo){ NodenewNode=newNode(); newNode.cargo=cargo; if(head==null){ head=newNode; newNode.next=null; length++; } else{ newNode.next=head; head=newNode; length++; }
524
node[i]=newNode(); node[i].cargo=word[i]; }
publicstaticvoidmain(String[]args){
//createanemptylist LinkedListlist=newLinkedList();
Nodenode2=newNode(); node2.cargo=newInteger(2);
Nodenode3=newNode(); node3.cargo=newInteger(3);
527
list.head=node1; list.length=3;
list.print(); list.printBackward();
this.cargo=cargo; this.next=next; }
publicStringtoString(){ returncargo+""; }
publicstaticvoidprintBackward(Nodelist){ if(list==null)return;
Nodehead=list; Nodetail=list.next;
printBackward(tail); System.out.print(head+","); } }
list.length=0; }
publicbooleanisEmpty(){ returnlist.head==null; }
publicvoidpush(Objecto){ list.addFirst(o); }
publicbooleanread(Stringfilename){
if(s==null) break; char[]kar=s.toCharArray(); for(inti=0;i<kar.length;i++){ if(kar[i]=='(') parenthesStack.push(newCharacter('(')); elseif(kar[i]==')'){ if(parenthesStack.isEmpty()) returnfalse; else parenthesStack.pop(); }
elseif(kar[i]=='[') bracketStack.push(newCharacter('[')); elseif(kar[i]==']'){ if(bracketStack.isEmpty()) returnfalse; else bracketStack.pop(); } elseif(kar[i]=='{'){ squigStack.push(newCharacter('{')); } elseif(kar[i]=='}'){ if(squigStack.isEmpty()) 532
publicstaticvoidmain(String[]args){ 533
System.out.println(newBalance().read("balance")); } }
classEvalPostfix{ publicstaticdoubleevalPostFix(Stringpostfix){ StringTokenizertoken=newStringTokenizer(postfix); Stackstack=newStack(); while(token.hasMoreTokens()){ Stringoperand=token.nextToken(); System.out.println(operand); try{ Doubleangka=Double.valueOf(operand); stack.push(angka);
publicstaticStringinputLoop()throwsIOException{ BufferedReaderreader=newBufferedReader(new InputStreamReader(System.in)); Stringresult=""; while(true){ System.out.print("=>"); Strings=reader.readLine(); if(s==null) break; elseif(isOperator(s)||isOperand(s)){ System.out.println(s); result+=s+""; } elseif(s.equals("quit")) break; } returnresult; 535
publicstaticbooleanisOperator(Stringoperand){ if(operand.equals("+")) returntrue; elseif(operand.equals("")) returntrue; elseif(operand.equals("*")) returntrue; elseif(operand.equals("/")) returntrue; else returnfalse;
536
publicstaticvoidmain(String[]args){ Strings="";
Bab16
latihan16.1 classQueue16_1{ publicObject[]array; publicintfirst,next;
537
publicbooleanisEmpty(){ returnfirst==next; }
publicQueue16_2(){ 538
publicbooleanisEmpty(){ returnfirst==next; }
privatebooleanisFull(){ return((next+1)%array.length==first); }
classSortedListextendsLinkedList{ publicSortedList(){ super(); } publicvoidadd(Comparableo){ Nodenode=super.head; intindeks=1; while(node!=null){ if(o.compareTo(node)!=1) break; indeks++; node=node.next; } Noden=(Node)o; //jikaindekssatumakagunakanmethodaddFirst if(indeks==1) super.addFirst(n.cargo); else super.add(indeks1,n.cargo); }
publicNoderemoveLast(){ returnsuper.removeLast(); }
541
publicbooleanisEmpty(){ returnsuper.isEmpty(); }
} 543
classEvent{ privatePriorityQueuequeue;
publicvoidadd(Dated){ queue.add(d); }
} }
} }
545
Bab17
latihan17.1 publicstaticvoidvisitPreorder(Treetree){ if(tree==null) return; tree.node.visit(); visitPreorder(tree.left); visitPreorder(tree.right); }
latihan17.2 importjava.util.*;
classPreIteratorimplementsIterator{
privateIteratoriter;
publicPreIterator(Treet){ iter=buildVector(t).iterator();
publicvoidremove(){ iter.remove(); }
546
publicbooleanhasNext(){ returniter.hasNext(); }
publicObjectnext(){ returniter.next(); }
importjava.util.*;
classTree{
publicTreeright;
publicNodegetNode(){ returnnode; }
publicPreIteratorpreorderIterator(){ returnnewPreIterator(this); }
publicstaticintlongestPath(Treetree){ 548
publicstaticvoidmain(String[]args){
System.out.println("panjangtree"+longestPath(root));
} }
549
publicvoidvisit(){ System.out.print(cargo+""); }
publicObjectgetCargo(){ returncargo; }
interfaceVisitable{ publicvoidvisit(); }
latihan17.5 importjava.util.*;
publicComparableTree(Comparablenode,Treeleft,Treeright){ 551
publicstaticNodefindMax(Treetree){
Nodemax=tree.node; if(tree.left!=null){ Nodeleft=findMax(tree.left); if(max.compareTo(left)==1) max=left; } if(tree.right!=null){ Noderight=findMax(tree.right); if(max.compareTo(right)==1) max=right; } returnmax;
publicstaticvoidmain(String[]args){
System.out.println("max="+findMax(root).getCargo());
latihan17.6 importjava.util.*;
publicComparablegetNode(){ returnnode; }
publicstaticbooleancontains(Objecto,SearchTreet){ Noden=(Node)o; if(n.compareTo(t.getNode())==0) returntrue; if(n.compareTo(t.getNode())==1){ if(t.left==null) returnfalse; returncontains(o,t.left); } else{ if(t.right==null) returnfalse; returncontains(o,t.right); } }
latihan17.817.9
importjava.util.*;
returnnewset;
} 555
publicstaticTreeSetintersection(Setset1,Setset2){ Iteratoriter1=set1.iterator();
returnnewset; } }
Bab18
latihan18.118.2dan18.7 importjava.util.*;
publicHeap(){ 556
array=newint[128]; size=0; }
publicObjectgetCargo(inti){ returnarray[i]; }
publicvoidsetCargo(inti,into){ array[i]=o; }
publicintgetLeft(inti){ return2*i; }
publicvoidadd(into){ array[size]=o; intindeks=size; intparent=getParent(size); while(indeks!=0){ if(array[parent]<array[indeks]){ inttemp=array[parent]; array[parent]=array[indeks]; array[indeks]=temp; indeks=parent; parent=getParent(indeks); } else break; } size++;
} 558
publicstaticbooleanisComplete(Treetree){ if(tree.left==null&&tree.right==null) returntrue; intleftHeight=Tree.longestPath(tree.left); intrightHeight=Tree.longestPath(tree.right); if(leftHeight==1&&rightHeight==1) returntrue; if(leftHeight==rightHeight||leftHeight==rightHeight+1){ if(isComplete(tree.left)){ if(isComplete(tree.right)){ returntrue; } } 560
} returnfalse; }
publicstaticbooleanisHeapProperty(Treetree){ if(tree.left==null||tree.right==null) returntrue; Nodecargo=tree.getNode(); Nodeleft=tree.left.getNode(); Noderight=tree.right.getNode(); if(cargo.compareTo(left)!=1&&cargo.compareTo(right)!=1) if(isHeapProperty(tree.left)) if(isHeapProperty(tree.right)) returntrue;
returnfalse;
heap.add(56); heap.add(57); heap.add(18); heap.add(20); heap.add(14); heap.add(28); heap.add(20); heap.print(); heap.add(68); heap.print(); heap.remove(68); } }
importjava.util.*;
classTree{
publicNodegetNode(){ returnnode; }
publicstaticvoidmain(String[]args){
Treet1=newTree(newNode(2),null,null); 563
System.out.println("panjangtree"+longestPath(root));
} }
publicvoidvisit(){ System.out.print(cargo+""); }
publicObjectgetCargo(){ returncargo; }
564
interfaceVisitable{ publicvoidvisit(); }
latihan18.3 79 65
60
56571820 142820
7968655660182014282057
565
latihan18.5 ndiv2
latihan18.6 n+1
Bab19
Latihan19.1
importjava.util.*;
publicclassMyMap{ Vectorentries;
publicMyMap(){ entries=newVector(); }
566
returnentry.value; } } returnnull; }
567
} }
classEntry{ Objectkey,value;
568
publicEntry(Objectkey,Objectvalue){
return"{"+key+","+value+"}"; } }
Latihan19.3 21
Latihan19.5 importjava.util.*;
569
publicintgetMonth(){ returnmonth; }
570
571
System.out.println(hasDuplicate(bday)); }
} } Latihan19.6
importjava.util.*;
classInvertible{ publicstaticbooleaninvertible(HashMapmap){ Setset=map.keySet(); Iteratoriter=set.iterator(); Listlist=newArrayList(); while(iter.hasNext()){ Objecto=map.get(iter.next()); if(list.contains(o)) returnfalse; else list.add(o); } returntrue; } } Latihan19.7
572
importjava.io.BufferedReader; importjava.io.FileInputStream; importjava.io.IOException; importjava.io.InputStreamReader; importjava.util.HashMap; importjava.util.Iterator; importjava.util.Map; importjava.util.PriorityQueue; importjava.util.Set; importjava.util.StringTokenizer;
publicclassExcercise197{
573
} while(true){ try{ Stringcontent=reader.readLine(); if(content==null) break; StringTokenizerst=newStringTokenizer(content); while(st.hasMoreTokens()){ numOfWord++; Stringstr=st.nextToken(); if(str.length()==1) continue; if(map.containsKey(str)){ int counter=((Integer)map.get(str)).intValue(); map.put(str,Integer.valueOf(counter+1)); }else map.put(str,Integer.valueOf(1));
ioe.printStackTrace(); } } } }
publicintgetNumOfDifferentWord(){ returnmap.size(); }
publicintgetNumOfWord(){ returnnumOfWord; }
} /** *@paramargs */ publicstaticvoidmain(String[]args){ //TODOAutogeneratedmethodstub Excercise197e=newExcercise197("../../thinkapjava.txt"); //jawabana System.out.println(e.getNumOfWord()); //jawabanb System.out.println(e.getNumOfDifferentWord()); //jawabanc System.out.println(e.getNumOfWord("encapsulation")); //jawaband 576
publicintgetFrequency(){ returnfrequency; }
publicStringgetWord(){ returnword; }
publicintcompareTo(Objecto){ 577
Latihan19.8 importjava.util.*;
returnfalse; }
publicstaticvoidmain(String[]args){ LinkedListlist=newLinkedList();
Nodenode2=newNode(); node2.cargo=newInteger(5);
list.head=node1; list.length=3;
System.out.println(list.containLoop()); }
Latihan19.9 importjava.util.*;
classNewMap{ Vectorentries;
publicNewMap(){ entries=newVector(); }
returnnull; }
publicstaticvoidmain(String[]args){ NewMapmap=newNewMap(); map.put("aa","dsdd"); map.put("saa","sdfdd"); map.put("saa","test"); Setset=map.keySet(); Iteratorit=set.iterator(); while(it.hasNext()){ Stringkey=(String)it.next(); System.out.println(key); System.out.println(map.get(key)); } } } PadaimplementasidiatasdigunakanVectoryangberisiLinkedList.Dimanaisidari MapdisimpandalamLinkedList.LinkedListyangdigunakanadalahLinkedListbawaan dariJavayangpadapaketjava.util.ElemenpertamaLinkedListadalahkuncientri
583
sedangElementerakhirLinkedListadalahnilaiyangdisimpandalamMap.
Latihan19.10 importjava.util.*;
publicvoidclear(){ map=newHashMap(); }
publicbooleanremoveAll(Collectionc){ Iteratorit=c.iterator();
584
publicvoidadd(Objecto){ map.put(o,null); } }
585
waktuhashmap1 waktutreemap2
importjava.util.*;
publicclassBencmark{ HashMaphashMap=newHashMap(); TreeMaptreeMap=newTreeMap(); publicvoidadd(intn){ System.out.println("TESMETODEADD"); longtime=System.currentTimeMillis(); for(inti=1;i<=n;i++) hashMap.put(newInteger(i),"test"); longtime1=System.currentTimeMillis(); System.out.println("waktuhashmap"+(time1time));
time=System.currentTimeMillis();
586
publicvoidtestContains(){ System.out.println(); System.out.println(); System.out.println("TESMETODECONTAINS"); Iteratorkeys=hashMap.keySet().iterator(); longtime=System.currentTimeMillis(); while(keys.hasNext()){ hashMap.containsKey(keys.next()); } longtime1=System.currentTimeMillis(); System.out.println("waktuhashmap"+(time1time));
587
BAB20
Latihan20.12
publicclassFreqTabextendsHashMap{ 588
privatevoidbuildFrequencyTable(){ Stringcontent=""; while(true){ try{ content=reader.readLine(); if(content==null) break; char[]arr=content.toCharArray(); for(inti=0;i<arr.length;i++){ if(Character.isLetter(arr[i])){ increment(arr[i]); } } 589
publicvoidprint(){ 590
Latihan20.13 importjava.util.*;
publicclasspairimplementsComparable{ intfrequency;
591
charkarakter;
publicpair(){ }
publicintgetFrequency(){ returnfrequency; }
publicchargetKarakter(){ returnkarakter; }
592
return0; } } DefinisiFreqTabyangmenggunakanpair importjava.io.BufferedReader; importjava.io.FileInputStream; importjava.io.IOException; importjava.io.InputStreamReader; importjava.util.HashMap; importjava.util.Iterator; importjava.util.Map; importjava.util.PriorityQueue;
publicclassFreqTabextendsHashMap{
publicFreqTab(){
privatevoidbuildFrequencyTable(){ Stringcontent=""; while(true){ try{ content=reader.readLine(); if(content==null) break; char[]arr=content.toCharArray(); for(inti=0;i<arr.length;i++){ if(Character.isLetter(arr[i])){ 594
595
publicvoidprint(){ Iteratoriter=map.keySet().iterator(); PriorityQueuequeue=newPriorityQueue(); while(iter.hasNext()){ Characterkey=(Character)iter.next(); pairp=new pair(key.charValue(),((Integer)map.get(key)).intValue()); queue.add(p); } while(!queue.isEmpty()){ Objecto=queue.remove(); pairpairobj=(pair)o; System.out.println(pairobj.getKarakter()+" "+pairobj.getFrequency()); } }
596
} Latihan20.14
latihan20.15
importjava.io.*; importjava.util.*;
publicclassHuffTreeextendspair{ HuffTreeleft,right;
this.left=left; this.right=right; }
publicintcompareTo(Objecto){ returnsuper.compareTo(o); }
publicHuffTreegetLeft(){ returnleft; }
publicHuffTreegetRight(){ returnright; }
publicstaticHuffTreebuild(FreqTabft){ 598
Mapmap=ft.getMap(); Iteratoriter=map.keySet().iterator(); PriorityQueuequeue=newPriorityQueue(); while(iter.hasNext()){ Characterkey=(Character)iter.next(); HuffTreeht=new HuffTree(key.charValue(),((Integer)map.get(key)).intValue(),null,null); queue.add(ht); } while(!queue.isEmpty()){ Objecto=queue.remove(); HuffTreeht=(HuffTree)o; o=queue.remove(); HuffTreeht1=(HuffTree)o; HuffTreejoin=newHuffTree(' ',ht.getFrequency()+ht1.getFrequency(),ht,ht1); if(queue.isEmpty()){ returnjoin; }else{ queue.add(join);
} }
returnnull; 599
} }
600
publicStringdecode(Stringteks){ char[]arr=teks.toCharArray(); HuffTreetree=this.tree; Stringresult=""; for(inti=0;i<arr.length;i++){ if(arr[i]=='.'){ tree=tree.left; } elseif(arr[i]==''){ tree=tree.right; } if(tree.left==null&&tree.right==null){ result+=tree.karakter; tree=this.tree; } } returnresult; } }
Latihan20.18 importjava.util.*;
classCodeTabextendsHashMap{ 601
publicvoidgetCodes(){ traverseTree(root,""); }
ft.buildFrequencyTable(text); tree=HuffTree.build(ft); }
publicStringdecode(Stringteks){ char[]arr=teks.toCharArray(); HuffTreetree=this.tree; Stringresult=""; for(inti=0;i<arr.length;i++){ if(arr[i]=='.'){ tree=tree.left; } elseif(arr[i]==''){ tree=tree.right; } if(tree.left==null&&tree.right==null){ result+=tree.karakter; tree=this.tree; } } returnresult; }
publicstaticvoidmain(String[]args){ Stringteks=""; for(inti=1;i<=40;i++) teks+="e"; for(inti=1;i<=32;i++) teks+="a"; for(inti=1;i<=24;i++) teks+="t"; for(inti=1;i<=22;i++) teks+="s"; for(inti=1;i<=20;i++) teks+="n"; for(inti=1;i<=19;i++) teks+="r"; 604
605
History
1994,TulisanOriginalOlegAllenDowney 2007,PenerjemahandanPenambahanlampiranForeachdanGenerikolehWim Permana,MuhammadFuadDwiRizki,danAgusJuliardi
GNUFreeDocumentationLicense
Version1.2,November2002
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
0.PREAMBLE ThepurposeofthisLicenseistomakeamanual,textbook,orotherfunctionaland usefuldocument"free"inthesenseoffreedom:toassureeveryonetheeffective freedomtocopyandredistributeit,withorwithoutmodifyingit,eithercommerciallyor noncommercially.Secondarily,thisLicensepreservesfortheauthorandpublishera waytogetcreditfortheirwork,whilenotbeingconsideredresponsiblefor modificationsmadebyothers. ThisLicenseisakindof"copyleft",whichmeansthatderivativeworksofthedocument mustthemselvesbefreeinthesamesense.ItcomplementstheGNUGeneralPublic License,whichisacopyleftlicensedesignedforfreesoftware. WehavedesignedthisLicenseinordertouseitformanualsforfreesoftware,because 606
freesoftwareneedsfreedocumentation:afreeprogramshouldcomewithmanuals providingthesamefreedomsthatthesoftwaredoes.ButthisLicenseisnotlimitedto softwaremanuals;itcanbeusedforanytextualwork,regardlessofsubjectmatteror whetheritispublishedasaprintedbook.WerecommendthisLicenseprincipallyfor workswhosepurposeisinstructionorreference. 1.APPLICABILITYANDDEFINITIONS ThisLicenseappliestoanymanualorotherwork,inanymedium,thatcontainsanotice placedbythecopyrightholdersayingitcanbedistributedunderthetermsofthis License.Suchanoticegrantsaworldwide,royaltyfreelicense,unlimitedinduration, tousethatworkundertheconditionsstatedherein.The"Document",below,refersto anysuchmanualorwork.Anymemberofthepublicisalicensee,andisaddressedas "you".Youacceptthelicenseifyoucopy,modifyordistributetheworkinaway requiringpermissionundercopyrightlaw. A"ModifiedVersion"oftheDocumentmeansanyworkcontainingtheDocumentora portionofit,eithercopiedverbatim,orwithmodificationsand/ortranslatedinto anotherlanguage. A"SecondarySection"isanamedappendixorafrontmattersectionoftheDocument thatdealsexclusivelywiththerelationshipofthepublishersorauthorsoftheDocument totheDocument'soverallsubject(ortorelatedmatters)andcontainsnothingthatcould falldirectlywithinthatoverallsubject.(Thus,iftheDocumentisinpartatextbookof mathematics,aSecondarySectionmaynotexplainanymathematics.)Therelationship couldbeamatterofhistoricalconnectionwiththesubjectorwithrelatedmatters,orof legal,commercial,philosophical,ethicalorpoliticalpositionregardingthem. The"InvariantSections"arecertainSecondarySectionswhosetitlesaredesignated,
607