Anda di halaman 1dari 607

BAGAIMANACARABERPIKIRSEBAGAIILMUWANKOMPUTER VersiJava

Pengarang AllenB.Downey

Penerjemah WimPermana,wimkhan@yahoo.com (Bab617) MuhammadFuadDwiRizki,fuad1986@gmail.com (Bab5,18,19,20) (LampiranForeachDanGenerik) (JawabanLatihan) AgusJuliardi (Bab14)

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)

Terjemahan, Lampiran Foreach dan Generik, dan

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.

Dilevelpertama,Andaakanbelajarprogramyangmerupakankemampuanberguna untukdirisendiri.DilevellainnyaAndaakanmenggunakanpemrogramanyangberarti suatuberakhir.Jikakitapelanmakaakhirnyaakanmenjadijelas.

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.

Sebagaicontoh,dalambahasainggris,sebuahkalimatharusdimulaidenganhurufbesar dandiakhiridenganperiode.Kalimatmengandungsyntaxerror.Begitupundenganyang satuini.Untukkebanyakanpembaca,beberapasyntaxyangerrorbukanlahmasalah yangsignifikan.Yangmanasamahalnyakenapakitamembacapuisiyangmengabaikan apabilaadakesalahan. 18

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).

PadaJavaruntimeerrordinamakanexceptions,danpadakebanyakanenvironmentitu munculpadawindowsdengankotakdialog yangmengandunginformasitentangapa yangterjadidanapayangprogramkanketikaituterjadi.Informasiinibergunauntuk 19

prosesDebugging.

1.3.3Logicserrordansemantics Tipeketigadarierroradalahlogicaldansemanticserrror.Jikaadalogicalerrorpada programAnda,makaakandicompiledanberhasildirundenganpengertiankomputer tidakakanmengeneratesetiappesankesalahan.Akantetapihalitubukanhalyang benar. Adahal lainyangakandilakukan yaituprogrammelakukanapayanganda suruh.

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.

Dengankatalaindebuggingsepertipekerjaandetektif.Andadihadapkanpadapetunjuk, danandaharusmenyimpulkanprosesdankejadianyangmengarahpadahasilyanganda lihat.

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.

Sebagaicontoh,Linuxadalahsistemoperasiyangterdiridariberibubariskodeakan tetapiituawalnyaberasaldariprogramsederhanaLinusTovardsyangdigunakanuntuk mengeksplorasiIntel3086Chips.MenurutLarryGrandfieldSatudariLinusproject adalahsebuahprogramyangberasaldaricetakanAAAAdanBBBBB. Ininantinya akanmenjadiLinux.(PanduanPemakaiLinuxBetaversi1).

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:

Puisi:Katakatadigunakanuntukbunyinyajugauntukmaksud/artinya,dansyair/puisi yangutuhbersamasamamenciptakansuatuefekatautanggapanemosional.Kerancuan seringmerupakankesengajaan.

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{

//main:generatesomesimpleoutput publicstaticvoidmain(String[]args){ System.out.println("Hello,world."); } }

Sebagian orang menilai mutu suatu bahasa program terlihat dari kesederhanaannya HelloWorld"Program.Denganstandardini,bahasaJavatidakmelakukanseluruhnya denganbaik.Bahkanprogramyangpalingsederhanaberisisejumlahcodeyangsulit dijelaskanpadaparaprogrammerpemula.Marikitaabaikansemuanyaterlebihdahulu. Sekarang,sayaakanmenjelaskanbeberapa.

Semuaprogramterdiridaridefinisikelas,yangmempunyaiformat:

classCLASSNAME{ publicstaticvoidmain(String[]args){ STATEMENTS } }

DisiniCLASSNAMEmenunjukkanbahwasuatunamadapatandatentukansendiri. NamakelaspadacontohiniadalahHello. 25

Padabarisyangkedua,katapublicstaticvoidandaabaikandulu,tetapiperhatikankata main.mainadalahsuatunamakhususyangmenandaitempatdimanaprogramakan mulai.Ketikaprogramberjalan,programakanmulaidenganmengeksekusistatemendi dalammaindanituberlanjutsampaisampaiakhirstatemen,dankemudiankeluar.

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!

a.Didalamkomputerjargon,apaperbedaanantarasuatustatemendansuatukomentar? b.Apaartinyabahwasuatuprogramdikatakanportable? c.Apayangdimaksuddenganexecutable?

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

BabII VariabeldanTipenya 2.1Mencetaklebihbanyak


Sepertiyangtelahsayasebutkanpadababyanglalu,Andadapatmeletakkansebanyak apapunstatemenpadamain.Sebagaicontoh,untukmencetaklebihdarisatubaris:

classHello{ //main:generatesomesimpleoutput publicstaticvoidmain(String[]args){ System.out.println("Hello,world."); System.out.println("Howareyou?"); } } //printoneline //printanother

Juga,sepertiyangandalihat,adalahlegaluntukmenaruhkomentarpadaakhirsuatu baris,sepertihalnyasejajardenganbarisitu.Ungkapanyangnampaktandakutipnya disebutstring,sebabkarenaterdiridarisuatuurutanstringhuruf.sebetulnya,string bisaberisikombinasihuruf,angkaangka,tandabaca,dankarekterkhususlainnya.

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:

//main:generatesomesimpleoutput publicstaticvoidmain(String[]args){ System.out.print("Goodbye,"); System.out.println("cruelworld!"); } }

Dalamhalinikeluaranakannampak padasatubarissepertiGoodbye,cruelworld!. PerhatikanbahwaadasuatuspasiantarakataGoodbyedantandakutipyangkedua. SpasiinimunculpadaOutput,danmempunyaiefekpadaprogram.Spasiyangmuncul diluartandakutipbiasanyatidakmempunyaiefekpadaprogram.Sebagaicontoh,saya bisasudahmenulis:

classHello{ publicstaticvoidmain(String[]args){ System.out.print("Goodbye,"); System.out.println("cruelworld!"); } }

PrograminiakandicompiledandiRunsamahalnyasebelumnya.Tulisanpadabagian akhir ( newlines) juga tidak mempunyai efek pada program, maka saya bisa sudah menulis:

32

classHello{publicstaticvoidmain(String[]args){ System.out.print("Goodbye,");System.out.println ("cruelworld!");}}

Inijugabisa,walaupunandamungkinmelihatbahwaprogrammenjadisemakinsulit danlebihsulituntukmembaca.Barisbarudanspasibermanfaatuntukmengorganisir programandasecaravisual,membuatprogramlebihmudahuntukmembacaprogram itudanmenempatkankesalahansintax.

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.

Dalam menyimpan suatu nilai,anda harusmenciptakansuatu variabel. Karenanilai yanginginkitasimpanadalahstring,makakitaakanmendeklarasikanvariabelbaru sebagaisuatustring:

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.

Untukmembuatsuatuvariabelbilanganbulat,sintaknyasepertiintbob;,dimanabob adalahnamayangdapatandatulissembarang.Secaraumum,andaakanmenulissuatu namavariabelyangmengindikasikanvariabelyanginginandabentuk.Sebagaicontoh, jikaandamelihatdeklarasivariabelini:

StringfirstName; StringlastName; inthour,minute;

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

Contohinimenunjukkantigaassignment,dankomentarmenunjukkantigaperbedaan caraorangmenyatakantentangassignmentstatement.Kosakatanyajadimeragukandi sini,tetapigagasansecaralangsung:

ketika anda mendeklarasikan suatu variabel, anda menciptakan suatu nama untuklokasipenyimpanan.

Ketikaandamekanassignmentterhadapsuatuvariabel,andamemberinyasuatu nilai.

Suatucaraumumuntukmempresentasikansuatuvariabelsecaratertulisadalahdengan menggambarkansuatukotakdengannamavariabeldiluarnyadannilaivariabelpada didalamnya.Gambarinimenunjukkanefekdariketigaassignmentstatemen:

Untuk masingmasing variabel, nama variabel nampak di luar kotak itu dan nilai nampakdidalam.

Padaumumnya,suatuvariabelharusmempunyaitipeyangsamasepertimengassign nilai.Andatidakbisamenyimpansuatustringdidalamminuteatausuatubilanganbulat didalamfred.

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.

fred="123"; //legal fred=123; //notlegal

2.4MencetakVariabel
Anda dapat mencetak nilai suatu variabel menggunakan perintah yang sama seperti yangkitagunakanuntukmencetakStrings.

classHello{ publicstaticvoidmain(String[]args){ StringfirstLine; firstLine="Hello,again!"; System.out.println(firstLine); } }

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:

StringfirstLine; firstLine="Hello,again!"; System.out.print("ThevalueoffirstLineis"); System.out.println(firstLine);

Keluarandariprograminiadalah:

ThevalueoffirstLineisHello,again!

Saya senang untuk mengatakan bahwa sintak untuk mencetak suatu variabel adalah samahalnyadenganmengabaikanjenisvariabelitu.

inthour,minute; hour=11; minute=59; System.out.print("Thecurrenttimeis"); System.out.print(hour); System.out.print(":"); System.out.print(minute);

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:

inthour,minute; hour=11; minute=59;

39

System.out.print("Numberofminutessincemidnight:"); System.out.println(hour*60+minute); System.out.print("Fractionofthehourthathaspassed:"); System.out.println(minute/60);

akanmenghasilkankeluaranyangberikut:

Numberofminutessincemidnight:719 Fractionofthehourthathaspassed:0

Barisyangpertamaadalahapayangkitaharapkan,tetapibarisyangkeduaadalahaneh. Nilaimenitvariabeladalah59,dan59yangdibagioleh60adalah0.98333,bukan0. PertentanganinidisebabkanbahwaJavamekanpembagiandalambilanganbulat.

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).

Jikaoperatormempunyaikedudukanyangsamamakaakandievaluasidarikiri kekanan.Makadidalamungkapanini menit*100/60,perkaliandikanterlebih dulu,hasildari 5900/60adalah 98.Jikaoperasidikandarikanankekiri,hasil 59*1adalah59,danitusalah.

KapanpunJikaandainginmengesampingkanketentuanketentuannilaiprecende ( atau anda tidak tahu pasti apa hasilnya) anda dapat menggunakan tanda kurung.Ungkapandidalamtandakurungdievaluasiterlebihdahulu,maka2*

41

(31) 4.Anda dapatjugamenggunakantandakurunguntukmembuatsuatu ungkapanlebihmudahuntukmembaca,sepertidi(menit*100)/60,walaupun itutidakmengubahhasil.

2.8 perator O pada String

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);

Sebenarnya,sayaseharusnyatidakmengatakanpadawaktuyangsama,"karenapada kenyataannyaperkalianharusterjadisebelumpencetakan,tetapiintinyaadalahbahwa ungkapanmanapunmenyertakanangkaangka,string,danvariabel,dapatdigunakandi dalamsuatustatemencetakan.Kitatelahmelihatsatucontoh:

System.out.println(hour*60+minute);

Tetapiandadapatjugamenaruhungkapanpadasembarangtempatpadasisikanandari suatustatementugas:

intpercentage; percentage=(minute*100)/60;

43

Kemampuaninitidaklaginampaksangatmengesankansekarang,tetapikitaakanlihat contohlaindimanakomposisimemungkinkanuntukmenyatakanperhitungankompleks denganrapidandengansingkat.

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.

Keyword:Suatukatadigunakanolehcompileruntukmenguraikan(kalimat)program. andatidakbisamenggunakankatakuncisepertpublic,classdanvoidsebagainama variabel.

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.

Expression:Suatukombinasivariabel,operatordannilainilaiyangmempresentasikan hasilnilaitunggal.Ungkapanjugamempunyaitipeyangditentukanolehoperatordan operand.

Operator:Suatulambangkhususyangmempresentasikansuatuperhitungansederhana sepertiaddition,multiplicationataupenggabunganstring.

Operands:Salahsatudarinilainilaidimanadiatasnyasuatuoperatorberoperasi.

Precedence:Kedudukansuatuoperatorketikasuatuoperasidievaluasi

Concatenate:Untukmenggabungkanujungujungduaoperand.

Komposisi:Kemampuanuntukmengkombinasikanstatemendanekspresisederhanake dalamstatemencampurandanekspresiekspresiuntukmempresentasikanperhitungan kompleksdengansingkat. 45

2.11Latihanlatihan

Latihan2.1 a.CiptakansuatuprogrambarunamaDate.Java.CopyatauketiksesuatusepertiHello, World"yakinkanandadapatmengcompiledanRunnya.

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.

e.Buatprogramuntukmengkalkulasi danmencetak persentasedarihariyangtelah lewat. 47

f. Ubah nilainilai jam, menit dan detik untuk mencerminkan waktu yang sekarang (sayaberasumsibahwawaktutelahberlalu),danperiksauntukmeyakinkanbahwa programdapatbekerjadengantepatdengannilainilaiyangberbeda.

Intidarilatihaniniadalahuntukmenggunakansebagiandarioperasiperhitungan,dan untukmemulaiberpikirtentangcampuranvariabelsepertijamyangdipresentasikan denganbanyaknilai.Juga,andamungkinmenemukanpermasalahandalammenghitung persentasedengan ints,yangmanaadalahmotivasiuntukbelajar floatingpoint pada yangberikutnya.

SYARAT:andabolehmenggunakanvariabeltambahanuntukmenyimpannilainilai yanguntuksementarasepanjangperhitunganitu.Variabelsepertiini,digunakanpada komputasitetapitidakpernahdicetakyangterkadangdisebutdenganintermediateatau variabeltemporer.

48

BABIII Method 3.1Floatingpoint

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;

Sebabvariabelpadasisikiriadalahsuatuintdannilaipadasisikananadalahsuatu double.makamudahuntukmelupakanaturanini,kususnyakarenaadatempatdimana javaakansecaraotomatismengkonversidarisatutipekelain.Sebagaicontoh:

doubley=1;

seharusnyasecarateknistidakbenar,tetapiJavamengijinkandenganmengubahintitu kepadasuatudoublesecaraotomatis.Kemudahaninisangatmenyenangkan,tetapiitu dapatmenyebabkanpermasalahan; sebagaicontoh:

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

bulatadalahmenggunakantypecast.Dinamakantypecastingkarenamengijinkananda untukmengambilsuatutipenilaidanmengubahnyakedalamtipelain(dalampengertian mengubahtidakmelempar).

Sayangnya,sintaks untuktypecastingjelek: andamenaruhnama tipedidalam tanda kurungdanmenggunakannyasebagaisuatuoperator.Sebagaicontoh,

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:

doubleroot=Math.sqrt(17.0); doubleangle=1.5; doubleheight=Math.sin(angle);

Contohyangpertamaakar17.Contohyangkeduasinus1.5,yangmanaadalahnilai sudutvariabel.Javaberasumsibahwa nilainilaiyangandagunakandengansindan

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:

publicstaticvoidmain(String[]args){ System.out.println("Firstline."); newLine(); System.out.println("Secondline."); }

56

Keluarandariprograminiadalah

Firstline. Secondline.

Perhatikanspasiantarakeduabentuk.Akibatnyabagaimanajikakitainginmenambah spasiantaraduabaris?Kitabisamemanggilmethodyangsamaberulangkali:

publicstaticvoidmain(String[]args){ System.out.println("Firstline."); newLine(); newLine(); newLine(); System.out.println("Secondline."); }

AtaukitabisamenulissuatumetodabaruyangdinamakanthreeLineyangmencetak tigabentukbaru:

publicstaticvoidthreeLine(){ newLine();newLine();newLine(); } publicstaticvoidmain(String[]args){ System.out.println("Firstline."); threeLine();

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.

Sejauhini,mungkinbelumbegitujelaskenapabegituberhargainiuntukmenciptakan semuametodabaruini.sebenarnya,adabanyakpertimbangan,tetapicontohinihanya mempertunjukkanduahal:

1.Menciptakansuatumethodbarumemberiandasuatukesempatanuntukmemberi suatu nama kepada satu kelompok statemen. Method dapat menyederhanakan suatu programdenganmenyembunyikansuatuperhitungankompleksdibelakangperintah 58

tunggal,dandenganpenggunaankataBahasaInggrissebagaipenggantikode.Lebih jelasnya,newLineatauSystem.Out.Println("")?

2.Menciptakansuatumethodbaruyangdapatmembuatsuatuprogramyanglebihkecil denganmenghilangkankodeberulang.Sebagaicontoh,bagaimanacaraandamencetak sembilanbarisbaruberurutan?AndabisamemanggilmethodthreeLinetigakali.

3.6Classdanmethod
Dari pengelompokkan kodekode dari bagian yang sebelumnya, maka keseluruhan definisikelaskelihatansepertiini:

classNewLine{ publicstaticvoidnewLine(){ System.out.println(""); }

publicstaticvoidthreeLine(){ newLine();newLine();newLine(); }

publicstaticvoidmain(String[]args){ System.out.println("Firstline."); threeLine(); System.out.println("Secondline."); } }

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();

StatemenyangpertamamemanggilmethodpowdidalamClassMath(Yangmenaikkan kekuatanargumentasiyangpertamakeargumentasiyangkedua).Statemenyangkedua memintamethodnewLinemetoda,Javamengasumsikan(dengantepat)didalamClass Newlines,yangmanasedangkitatulis.

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:

publicstaticvoidprintTwice(Stringphil){ System.out.println(phil); System.out.println(phil); }

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:

publicstaticvoidmain(String[]args){ Stringargument="Neversaynever."; printTwice(argument); }

Perhatikansesuatuyangsangatpentingdisini:namavariabelyangkitalewatkansebagai suatuargument(argument)tidakmekanapaapaterhadapparameter(phil).

Sayakatakanlagibahwa:

Namavariabelyangkitalewatkansebagaisuatuargumenttidakmekanapapun terhadapnamaparameter.

Itubisasamaataubisaberbeda,tetapipentinguntukmenyadaribahwaitubukanlahhal yangsama,kecualijikamempunyainilaiyangsama(dalamhalinistring" ("Don't


makemesaythistwice!")

Nilaiyangandanyatakansebagaisuatuargumentiharusmempunyaitipeyangsama denganparametermethodyangandapanggil.Aturaninisangatpenting,tetapihalini 64

seringmembuatkitabingungpadaJavauntukduapertimbangan:

Adabeberapametodayangdapatmenerimaargumentasidenganbanyaktipeberbeda. Sebagaicontoh,andadapatmengirimkantipemanapununtukprintdanprintln,danitu akanselalubenar.Halsemacaminimerupakansuatuexception,though.

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

Untukmasingmasingmethodadasuatukotakabuabuyangdinamakan frame yang berisiparametermethoddanvariabellokal.Namamethodnampakdiluarframe.Seperti biasanya,nilaidaritiapvariabeldigambarkdidalamsuatukotakdengannamavariabel disampingnya.

3.10MetodeDenganBanyakParameter
Sintak untuk mendeklarasikan dan memanggil method dengan berbagai parameter adalah suatu sumber kesalahan pada umumnya. Pertama, ingat bahwa anda harus mendeklarasikantipetiaptiapparameter.Sebagaicontoh

publicstaticvoidprintTime(inthour,intminute){ System.out.print(hour); System.out.print(":"); System.out.println(minute); }

Itubisajaditerkecohuntukmenulisintjam,menit,tetapiformatituhanyabenaruntuk mendeklarasikanvariabel,bukanuntukparameter.

Sumber kesalahan umum yang lain adalah bahwa anda tidak punya sesuatu untuk 66

mendeklarasikantipeargument.Yangberikutadalahsalah!

inthour=11; intminute=59; printTime(inthour,intminute);//WRONG!

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:

Apayangterjadijikaandamemintasuatumethoddanyangandatidakmekan apapundenganhasil(yaitu.andatidakmengassignnyapadasuatuvariabelatau menggunakannyasebagaibagiandariekspresiyangbesar)?

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.

a.Apakeluaranprogramyangberikut?Perhatikandimanaadaspasidandimanaada barisbaru. SYARAT:mulaidenganmenguraikankatakataapapingdanbaffleyangkanketikaitu dilibatkan.

b.Gambarsuatudiagramstackyangmenunjukkanstatusprogrampertamakali ping dilibatkan.

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("."); }

Latihan3.3 Latihaniniadalahuntukmeyakinkanbahwaandamemahamibagaimanacaramenulis danmemanggilmethodyangmengambilparameter.

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.

b.Ujimethodandadenganmemanggilnyadarimaindanmelewatkanargumentyang sesuai. Keluarannyaharusterlihat(kecualidatebolehberbeda):

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

Didalambagianyangterakhir,andamendapatkesempatanuntukmenulissuatumethod yangmemanggilsuatumethodyangandatulis.Kapansajaandamekannya,merupakan suatugagasanbaikuntukmengujimethodyangpertamasecarahatihatisebelumanda memulaimenulisyangkedua.Selainitu,andamungkinmenemukancaramekan debuggingduamethodpadawaktuyangsama,yangbisajadisangatsulit.Salahsatu tujuandarilatihaniniadalahuntukmempraktekkanpatternmatching:kemampuan untukmengenalisuatumasalahspesifiksebagaisuatukategoripermasalahanumum.

73

BAB4 Kondisionaldanrekursi 4.1Operatormodulus


OperatorModulusbekerjapadabilanganbulatdanmenghasilkansisa ketikaoperan yangpertamadibagiolehyangkedua.Di(dalam)Java,operatormodulusadalahsuatu tandapersen,%.Sintaksispersisnyasamahalnyauntuklainoperator:

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"); }

Ungkapandi(dalam)tandakurungdisebutkondisi.Jikabenar,kemudianstatemendi (dalam)tandakurungdieksekusi.Jikakondisitidaklahbenar,tidakdilakukanapapun. Kondisidapatberisioperatorperbandinganapapun,kadangkadangdisebutrelational operator:

x==y//xequalsy x!=y//xisnotequaltoy x>y//xisgreaterthany x<y//xislessthany x>=y//xisgreaterthanorequaltoy x<=y//xislessthanorequaltoy

Walaupunoperasiinimungkindikenalbaikolehanda,sintaksJavamenggunakannya sedikitberbedadarilambangmatematikaseperti=, dan .Suatukesalahanumum adalahuntukmenggunakan=tunggalsebagaigantisuatu==.Ingatbahwa=adalah operatortugas,dan==adalahsuatuoperatorperbandingan.Juga,tidakadahalseperti =<atau=>.

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:

if(x%2==0){ System.out.println("xiseven"); }else{ System.out.println("xisodd"); }

Jikasisaketikaxdibagioleh2adalahnol,kitamengetahuibahwaxmenjadigenap,dan kodeinimencetaksuatupesan.Jikakondisiadalahsalah,statemencetakanyangkedua akandieksekusi.Karenakondisiharussalahataubenar,makasalahsatudarialternafif akandieksekusi.

Jikaandaberpikirmungkinakanseringmengecekgenapatauganjil, andamungkin inginmembungkus"kodeatasdalamsuatumethod,sebagaiberikut:

publicstaticvoidprintParity(intx){ if(x%2==0){ System.out.println("xiseven"); }else{

76

System.out.println("xisodd"); } }

SekarangandamempunyaisuatumetodanamaprintParityyangakanmencetaksuatu pesansesuaiuntukbilanganbulatapapun.Di(dalam)metodemainandaakan memanggilmetodainisebagaiberikut:

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:

if(x>0){ System.out.println("xispositive"); }elseif(x<0){ system.out.println("xisnegative");

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:

if(x==0){ System.out.println("xiszero"); }else{ if(x>0){ System.out.println("xispositive"); }else{ System.out.println("xisnegative"); } }

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:

publicstaticvoidprintLogarithm(doublex){ if(x<=0.0){ System.out.println("Positivenumbersonly,please."); return; } doubleresult=Math.log(x); System.out.println("Thelogofxis"+result); }

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.

Halmacaminiadalahcontohsuatumasalahumumdi(dalam)merancangsuatubahasa program,bahwaadasuatukonflikantar[a]formalisme,yaitukebutuhanbahasaformal untuk mempunyaiaturansederhanadengansedikiteksepsi,dankenyamanan,yang merupakankebutuhanbahasaprogramagarmudahdigunakandalampraktek.

Yanglebihseringterjadiadalahkenyamananlahyangmenang,yangbiasnayabaik untukparaprogrammerahli,tetapitidakbaikuntukparaprogrammerpemula.Dalam buku ini saya sudah mencoba untuk menyederhanakan berbagai hal dengan menekankanaturandanpenghilanganbanyakperkecualian.

80

Meskipundemikian,adabaiknyauntukmengetahuibahwakapansajaandamencoba menambahkanduavariabel,jikasalahsatudarimerekaadalahsuatuString,makaJava akanmengkonversiyanglainmenjadiStringdanmelakukanpenggabunganString.Apa pendapatandajikaanda melakukansuatuoperasiantarasuatubilanganbulatdansuatufloatingpoint?

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:

publicstaticvoidcountdown(intn){ if(n==0){ System.out.println("Blastoff!"); }else{ System.out.println(n); countdown(n1); } }

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.

Countdownyangmendapatn=1kembali(return). Countdownyangmendapatn=2kembali(return). Countdownyangmendapatn=3kembali(return). Dankemudianandaadalahkemain.Sehinggatotalkeluarankelihatanseperti:


3 2

82

1 Blastoff!

Sebagaicontohkedua,marikitalihatlagidimetodanewLinedanthreeLine.

publicstaticvoidnewLine(){ System.out.println(""); } publicstaticvoidthreeLine(){ newLine();newLine();newLine(); }

Walaupunmetodediatasdapatbekerja,merekatidakakanbanyakbergunajikasaya inginmencetak2barisatau106.Suatualternatiflebihbaikadalahdengan

publicstaticvoidnLines(intn){ if(n>0){ System.out.println(""); nLines(n1); } }

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.

Di(dalam)kasusini, adalahsuatukeuntunganuntukterbiasadengankonvensidan menggunakannya,sehinggaakanmembuatprogramandalebihmudahuntukdipahami olehoranglain.Danpentingpulauntukmembedakanantara(sedikitnya)tigamacam aturan:

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.

RulesOfJava:IniadalahperaturantentangsemantikdanyangsyntacticJavayang tidakbisaandalanggar,sebabprogramyangdihasilkantidakakanbisadikompilasiatau dijalankan.Sebagaicontoh,faktabahwalambang+menghadirkanpenambahandan 85

penggabunganString.

GayaDanKonvensi:Adabanyakaturanyangtidaklahdipaksaolehcompiler,tetapiitu adalah penting untuk penulisan program yang benar, sehingga dapat didebug dan dimodifikasi,dandapatdibacaoranglain.Contohnyaadalahindentasidanpenempatan kurungkurawal,dankonvensiuntukmenamaivariabel,metodadankelas.

Selagisayaadalahpadatopik,andasudahmungkinmengertimulaisekarangbahwa namakelasselalumulaidenganhurufbesar,tetapivariabeldanmetodamulaidengan hurufkecil.Jikanamalebihdarisatukata,makaandabiasanyamembuathurufpertama setiapkatadenganhurufbesar,sepertidinewLinedanprintParity.

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"

TulissuatumetodabernamaisTriangleyangmengambil tigabilanganbulatsebagai argumen,danitumengembalikantrue/false,tergantungapakahandabisamembentuk nyamenjadisegitiga

Tujuanlatihaniniadalahuntukmenggunakanpernyataanbersyaratuntukmenulissuatu metodayangmengembalikansuatunilai.

Latihan4.3 Latihaninimeninjaualiraneksekusiprogramdenganberbagaimetoda.Bacakodeyang berikutdanjawabpertanyaandibawah.

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:

99bottlesofbeeronthewall,99bottlesofbeer,yatakeonedown,ya passitaround,98bottlesofbeeronthewall. Sajakberikutnyaserupakecualibanyakbotollebihsedikitsatusetiapsajak,sampai sajakterakhir: Nobottlesofbeeronthewall,nobottlesofbeer,yacanttakeonedown, yacantpassitaround,causetherearenomorebottlesofbeeronthe wall! Dankemudiannyanyianberakhir. 89

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?

publicclassNarf{ publicstaticvoidzoop(Stringfred,intbob){ System.out.println(fred); if(bob==5){ ping("not"); }else{ System.out.println("!"); } } publicstaticvoidmain(String[]args){

90

intbizz=5; intbuzz=2; zoop("justfor",bizz); clink(2*buzz); } publicstaticvoidclink(intfork){ System.out.print("It's"); zoop("breakfast",fork); } publicstaticvoidping(StringstrangStrung){ System.out.println("any"+strangStrung+"more"); } }

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

Bab5 Fruitfulmethods 5.1NilaiKembalian


Beberapametodebawaanyangtelahkitagunakan,sepertifungsiMath,telah menghasilkanhasil.Tujuandaripemanggilanmetodeadalahuntukmenghasilkan sebuahnilaibaru,yangbiasanyakitamasukkanpadasebuahvariabelyangmerupakan bagiandarisebuahekspresi.Misalnya
doublee=Math.exp(1.0); doubleheight=radius*Math.sin(angle);

Tetapisejauhinisemuametodeyangtelahkitatulisadalahmetodedengankembalian void;yaitumetodeyangtidakmengembalikannilai.Ketikaandamemanggilmetode void,iahanyaterdiriatassatubaris,tanpapemberiannilaikedalamsatuvariabel.


nLines(3); g.drawOval(0,0,width,height);

Padababini,kitaakanmenulismetodeyangmengembalikannilai,yangsayasebut sebagaifruitfulmethods,untuknamayanglebihbaik.Contohyangpertamaadalah area,yangmengambildoublesebagaiparameter,danmengembalikanluaslingkaran denganradiusyangdiberikan: publicstaticdoublearea(doubleradius){ } Halpertamayangharusandaperhatikanadalahawaldaridefinisimetodeadalah 93 doublearea=Math.PI*radius*radius; returnarea;

berbeda.Sebagaigantipublicstaticvoid,yangmenunjukkanmetodevoid,kita menggunakanpublicstaticdouble,yangmenunjukkannilaikembaliandarimetodeini adalahdouble.Sayamasihbelummenjelaskanapaitupublicstatictapitenanglah.

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).

Kadangkadangbergunajugauntukmemilikibeberapastatemenreturn,satudisetiap cabangkondisi: publicstaticdoubleabsoluteValue(doublex){ if(x<0){ returnx;

94

}else{ returnx; } Karenastatemenreturnadapadakondisialternatif,makahanyasatuyangakan dieksekusi.Meskipunsahuntukmemilikilebihdarisatustatemenreturndalamsatu metode,harusselaluandaingatbahwasegerasetelahdieksekusi,metodeakanberhenti tanpamengeksekusipernyataanyangadadibawahnyalagi.

Kodeyangadasetelahsebuahpernyataanreturn,ataudimanapundimanatidakakan pernahdieksekusi,disebutdeadcode.Beberapakompilerakanmemperingatkananda jikaadabagiankodeyangmengalamihalini.

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.

Padakasusini,duatitikadalahparameter,dansudahjamakuntukmewakilinyadengan 4double,meskipunkitaakanlihatnantiterdapatobjekPointpadaJavayangdapatkita gunakan.Nilaikembalianadalahjarak,yangakanberupadoublejuga.

Selanjutnyakitadapatmenulisgarisbesarmetodesebagaiberikut: publicstaticdoubledistance (doublex1,doubley1,doublex2,doubley2){ return0.0; }

96

Nilaikembalianreturn0.0;dibutuhkanagarprogramdapatdikompilasi.Padatahap iniprogramtidakmelakukanapapunyangberguna,tapiakanlebihbaikuntukmencoba mengkopilasisehinggakitabisamengetahuijikaterdapatsyntaksyangerrorsebelum kitamembuatnyamenjadilebihrumit.

Untukmengujimetodeyangbaru,kitaharusmenggunakannyadengannilaicontoh padametodemain: doubledist=distance(1.0,2.0,4.0,6.0); Sayamemilihnilainilaiinisehinggajarakhorizontaladalah3danjarakvertikaladalah 4.makahasilnyaakanmenjadi5.Ketikaandamengujisebuahmetodeakanberguna jikamengetahuijawabanyangbenar.

Ketikakitatelahmengeceksintakspadadefinisimetode,kitabisamemulaimenambah bariskode.Setelahsetiaptahapperubahan,kitamengkompilasilagidanmenjalankan program.Dengancaraini,kitamengetahuidengantepatdimanamasalahyangterjadi (jikaterdapaterror)yangpastipadabaristerakhiryangkitatambahkan.

Langkahberikutpadakomputasiadalahuntukmencarijarakantarax2x1dany2y1. Sayaakanmenyimpannilainilaiitupadavariabelsementarabernamadxdandy. publicstaticdoubledistance (doublex1,doubley1,doublex2,doubley2){ doubledx=x2x1; doubledy=y2y1; System.out.println("dxis"+dx); System.out.println("dyis"+dy); 97

return0.0; } Sayamenambahkanpernyataancetakyangmembuatsayabisamelihatnilaiyangada sebelumdiproses(jikaandamenggunakanIDE(IntegratedDevelopmentEnvironment) andabisamelakukanhalinitanpaSystem.out.printlndenganfiturdebugger,catatan penerjemah).Sebagaimanayangtelahsayasebutkan,sayatelahmengetahuibahwanilai nilaitersebutadalah3dan4.

Ketikametodetelahdiselesaikansayaakanmenghapusstatemencetaktersebut.Kode sepertiinidisebutscaffolding,karenaakanmembantudalammembuatprogram,tapi bukanmerupakanbagianprodukakhir.Kadangkadangmerupakanhalyangbaikuntuk tidakmenghapuskodescaffold,tetapihanyadibuatkomentar,hanyajikakirakiraanda akanmembutuhkannyalagi.

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.

Semakinandaberpengalamandalampemrograman,andaakanmakinmahirdanbisa menulisdanmendebugprogramlebihdarisatubarissetiapkali.Namundemikian prosespengembangansecarabertahapinibisamenghematbanyakwaktudebugging.

Halkuncipadaprosesadalah:

Mulaidenganprogramyangbisabekerjadanbuatperubahanbertahapyang kecil.Jikaterjadikesalahan,andaakanmengetahuidengantepatdiamania terjadi.

Gunakanvariabelsementarauntukmenyimpannilai(nilaiyangbukanhasil akhir)jadiandabisamencetakdanmengeceknya. 99

Ketikaprogrambekerja,andamungininginmenghapusbeberapabaris scaffoldingataumenggabungkanbeberapabaris/pernyattanmenjadisatutetapi hanyajikaitutidakmembuatprogramsulituntukdibaca.

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.

BanyakperintahbawaanJavayangdioverloading,yangberatiadaversiyangberbeda bedayangmenerimajumlahdantipeparameteryangberbeda.Misalnya,adaversiprint danprintlnyangmenerimasatuparameterdengantipeapapun.PadakelasMath,ada versiabsyangbekerjapadadoubledanadajugayangbekerjauntukint.

Meskipunoverloadingadalahmetodeyangberguna,iaseharusnyadipakaidenganhati hati.Andamungkinmenemukandiriandapusingsendirijikaandamencobamendebug satuversimetodepadahalsebenarnyaandamenggunakanversiyangberbeda.

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.

Pengecualianyangtelahkitalihatadalahoperatorrelasional,yangmembandingkanint danfloatdanmengembalikanapakahtrueataufalse.Truedanfalseadalahnilaikhusus dalamJava.Keduanyamerupakantipedataboolean.

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.

Sebagaimanayangtelahsayasebutkan,hasildarioperatorkondisionaladalahbooean, jadiandabisamenyimpanhasilpembandinganpadasebuahvariabel: booleanevenFlag=(n%2==0);//trueifniseven 103

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.

evenFlag||n%3==0 benarjikasalahsatudarikeduakondisibenar,jikaevenFlag bernilaibenarataunhabisdibagi3. NOToperatirmemilikiefekuntukmenegasikanataumenginversekspresiboolean,jadi !evenFlagbernilaibenarjikaevenFlagbernilaifalse,ataujikanbernilaiganjil.

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.

Kodenyasendiri samasaja,meskipunakanlebihpanjangsedikitdariseharusnnya. Ingatbahwaekspresix>=0&&x<10memilikitipeboolean,jaditidakadayangsalah denganmengembalikannyasecaralangsung,danmenghindaripernyataanmenggunakan if. publicstaticbooleanisSingleDigit(intx){ return(x>=0&&x<10); } Padametodemainandabisamemanggilmetodedengancarayangbiasa: 105

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.

Jikaandamelihatpadadefinisifaktorial,andamungkinmendapatkanseperti: 0!=1 n!=n(n1)! (Faktorialbiasanyadisimbolkandengan!,janganbingungdenganoperaror!PadaJava yangberartiNOT.)definisiinimenyatakanbahwafaktorial0adalah1,danfaktorial nilaiyanglain,adalahndikalikandenganfaktorialdarin1.Jadi3!adalah3kali2!, dimana2!faktorialadalah2kali1!,yangmerupakan1kali0!.Sehinggadidapatkan3! samadengan3kali2kali1kali1yangmenghasilkan6.

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

Karena0samadengan0,kitamengambil cabangpertamadanmengembalikannilai1tanpa memanggilmetoderekursif. Nilaikembalian1dikalikandengann,yaitu1,danhasilnya dikembalikan Nilaikembalian1dikalikandengann,yaitu2,danhasilnya dikembalikan. Nilaikembalian2dikalikandengann,yaitu3,danhasilnyaadalah6.dikembalikan padamain,yangmemanggilfaktorial(3).

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.

Tentu,merupakanhalyanganehuntukmengasumsikanmetodebekerjadenganbenar ketikakitabelumselesaimenuliskannya,tetapiitulahmengapakitamenyebutnyaleap 110

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

Tulislahmetodebernamadistanceyangmengambilempatdoublesebagaiparameter x1,y1,x2,y2danmencetakjarakantaratitik. AndaharusberasumsiterdapatmetodeyangbernamsumSquaresyangmenghitungdan mengembalikanjumlahdarikuadratargumennyasebagaicontoh: doublex=sumSquares(3.0,4.0); akanmenugaskan25kex. Tujuandarilatihaniniadalahmenulismetodebarudenganmenggunakanmetodeyang sudahada.Andaharushanyamenulissatumetode:distance.Andatidakharusmenulis sumSquaresataumaindanandatidakharusmemanggildistance

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.

Latihan5.6 TujuanlatihaniniadalahuntukmenerjemahkandefinisirekursifkedalammetodeJava. FungsiAckermandidefinisikanuntukbilanganbulatnonnegatifsebagaiberikut:

116

Tulismetodebernamaackyangmengambilduaintsebagaiparameter,menghitungdan mengembalikannilaidarifungsiAckerman.

Ujiimplementasiandadenganmemanggilnyadarimetode main danmencetaknilai kembaliannya.

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

Bab6 Iterasi 6.1 MultipleAssignment

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; }

Outputdariprograminitampaksebagaiberikut: 1.00.0 2.00.6931471805599453 3.01.0986122886681098 4.01.3862943611198906 5.01.6094379124341003 6.01.791759469228055 7.01.9459101490553132 127

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

pemanggilanmetode.Cool! Outputdariprograminiadalahsebagaiberikut: 123456 24681012 369121518 4812162024 51015202530 61218243036

Bagaimana?Tampaksepertitabelperkalianbukan?Meskipunbentuknyajugakelihatan 132

agakagakmiringsedikit.JikabentukbentuksepertiinimenggangguAnda,Javatelah menyediakan metodemetode yang dapat memberi Anda kendali lebih baik atas masalahmasalahoutput,tapisayabelummaubertamasyakesanasekarang.Tungguya!

6.7

Metode

Dalambagiansebelumnyasayamenyebutkan,"semuakebaikanyangdapatdiberikan olehmetode."Sebelumnya,mungkinAndaakanbertanyatanya,apasajasihkebaikan kebaikanyangdimaksud?Berikutiniadalahbeberapaalasanmengapametodemetode tersebutmempunyaiposisiyangsangatpenting:

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!

Untuk mendemonstrasikan enkapsulasilagi,Sayaakanmengambilkodedari bagian sebelumnyalalumembungkusnyadalamsebuahmetode: publicstaticvoidprintMultTable(){ 133

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

Heeee...bingungya.... Jawabanuntukkeduapertanyaantersebutadalah"tidak,"karenavariabelidimetode printMultiples dan i dalam printMultTable adalah duavariabel

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

6. Anda dapat menambahkan sebuah parameter ke dalam metode printMultTable :

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)

tabel7x7yangtampaklebih"kotak": 1234567 2468101214 137

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:

printMultiples(i,high); menjadi printMultiples(i,i);

denganpengubahaniniAndaakanmendapatkanhasilsebagaiberikut: 1 24 369 481216 510152025 61218243036 7142128354249

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

Arti babini,sayamendemonstrasikansebuahteknikpengembangan yangberbasispadapengembangankodeuntukmelakukan sesuatuyangsederhana,khusus,lalumengenkapsulasidan menggeneralisasinya.Dalambagian5.2saya mendemonstrasikansebuahteknikyangsayasebut pengembanganbertingkat.Dibabbabakhirsayaakan menunjukkanteknikpengembanganyanglain.

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){

a) Buatlahsebuahtabelyangdapatmenunjukkannilaidarivariabelidannselamaloop sedangdieksekusi.Tabeltersebutharusberisisatukolomuntuksetiapvariabeldan 140

satubarisuntuksetiapiterasi. b) Apaoutputdariprogramini?

Latihan6.2 a) Enkapsulasilahfragmenkodedibawahini,kemudianubahlahbentuknyakedalam metodeyangmenggunakansebuahvariabelbertipeStringsebagaiargumennyadan mengembalikan(tapibukanmencetak)nilaiterakhirdaricount. b) Dalamsebuahkalimat,deskripsikansecaraabstrakapayangtelahdihasilkanoleh metodebuatanAndatersebut. c) AsumsikanbahwaAndatelahmenggeneralisasimetodeberikutinisehinggaiadapat digunakanuntuksemuaString.MenurutAnda,kirakiraapalagiyangdapatAnda lakukansehinggametodetersebutdapatlebihtergeneralisasi?


String s= "((3+ 7)* 2)"; intlen =s.length (); inti =0; intcount = 0; while (i< len){ char c =s.charAt(i); if (c== '(') { count = count +1; } else if(c ==')') { count = count 1; } i =i+ 1; } System.out.pr intln (count);

141

Latihan6.3 MisalkanAndadiberisebuahbilangan,misalkan a,laluAndainginmenemukannilai akarnya.Salahsatucarayangdapatdigunakanadalahdenganmenebakmentahmentah nilaitersebutdengansebuahbilanganmisalkan,xo.Lalu,menaikkantingkatkebenaran bilangantersebutdenganmenggunakanrumusberikutini: x1 =( x 0 + a/x 0 )/2 (6.2)

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.

Latihan6.5 Bagian5.10memperlihatkansebuahmetoderekursifyangmenghitungnilaidarifungsi faktorial.Tulislahsebuahversiiteratifdarimetodefaktorial.

Latihan6.6 Salahsatucarauntukmenghitungexadalahdenganmenggunakanbentukekspansitak hinggaberikutini: e x =1+x+x


2

/2!+x 3 /3!+x 4 /4!+....(6.3)

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

Bab7 String 7.1 Memanggilmetodedalamobjek

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

http://java.sun.com/javase/6/docs/api/java/lang/String.html, lalu Anda mengklik link charAt,Andaakanmendapatkandokumentasiyangtampak(mungkinmirip)sepertidi bawahini:


public char charAt(int index)

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.

Jikaindeksmulaibernilainegatif,hasilnyaadalah1.hasilinimengindikasikan bahwakemunculanpertamahurufyangdicariberadadalamindeksyanglebih besardaripadanilaiindeksmulai.

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.

Incrementberarti menaikkan/menambahkan nilaisuatuvariabeldengannilai satu(1)secaraberulangulangsampaisyaratyangditetapkanbernilaifalse.

Decrementberarti menurunkan/mengurangi nilaisuatuvariabeldengannilai satu(1)secaraberulangulangsampaisyaratyangditetapkanbernilaifalse.

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

KetikaAndamelihatlihatkembalidokumentasiuntukmetodeString,Andamungkin akanmemperhatikanmetodetoUpperCasedantoLowerCase.Metodeiniseringmenjadi biangmasalah.Kokbisa?Karenakeduanyatampakseolaholahtelahmengubahstring yangsudahadakebentuklainnya.Padahal,sebenarnyatidakadasatupunmetodeyang dapatmengubahsuatustring,karenastringmemangbersifat immune aliastidakbisa 155

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

Sebagaipelengkap,sayaharusmengakuibahwaadalah legal dalamJava,meskipun jarangsekalibenar,menggunakanoperator'=='untuktipedataString.Andamengerti maksudsaya?Tidak!Ituwajar,karenapembahasannyaakanberadadibagianbagian berikutnya.Sabarya.....

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.

7.12 Latihan Latihan7.1


Inti dari latihan ini adalah untuk mencoba beberapa operasi yang berkaitan dengan Stringdanmemasukkanbeberapabagianyangbelumdibahasdalambagianini. a) BuatlahsebuahprogramdengannamaTest.java,lalubuatlahsebuahmetodemain yang berisi ekspresiekspresi yang mengkombinasikan beberapa tipe data menggunakan operator ' + '. Sebagai contoh, apa yang akan terjadi jika Anda menambahkan sebuah String dan sebuah char? Apakah ekspresi ini akan menghasilkanpenambahan(addition)ataupenggabungan(concatenation). b) Buatlahtabelyanglebihbesarketimbangtabeldibawahini!Laluisilahsetiapirisan (interseksi) yang terjadi antara tipe datatipe data ini dengan informasi yang memberitahulegaltidaknyapenggunaanoperasi'+'.Jikalegal,makatermasuk kategoriyangmanakahoperasitersebut.Apakahpenambahanataupenggabungan. c) BayangkandanpikirkanlahbeberapapilihanyangtelahdibuatolehdeveloperJava ketika mereka hendak mengisi tabel ini. Berapa entri di dalamnya yang tampak masuk akal, jika kemungkinan untuk masuk akal itu sendiri mungkin tidak ada? Berapabanyakdiantaranyayangtampaksepertihasildaripemilihanacakatausuka suka (arbitrary) dari beberapa kemungkinan yang masuk akal? Berapa banyak diantaranyayangkelihatansebagaihasilpilihanbodoh? d) Waktunyabermaintekateki:normalnya,pernyataanx++equivalendenganx=x+ 1. Kecuali jika x adalah char. Dalam kasus ini, x++ adalah sesuatu yang legal. Namuntidakdenganx=x+1.

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

Bab8 InterestingObjects 8.1 Apanyayangmenarik?

MeskipunStringadalahobjek,tapimerekabukanlahobjekyangbenarbenarmenarik. Maklum,Stringitu:

Tidakbisadiubahubahaliasimmutable. Merekatidakmempunyaivariabelinstan. Tidakmengharuskankitauntukmenggunakanperintahnewketikamembuatnya.

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

Kumpulandatayangmenyusunsebuahobjekseringjugadisebutsebagaikomponen, rekaman(record),ataufield.DalamJava,merekadisebutsebagaivariabelinstankarena 170

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

Andadapatmelewatkan(pass)suatuobjeksebagaiparameterdengancarayangsudah lazimdigunakan.Contoh, publicstaticvoidprintPoint(Pointp){ 171

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

mengacukepadanya.Gambarberikutiniakanmenunjukkanefekdariassignmentini. JikaAndamencetakbox,Andaakanmendapatkan java.awt.Rectangle[x=0,y=0,width=100,height=200] Lagilagi,inimerupakanhasildarimetodebawaanJavayangsudahtahubagaimana caranyamencetakobjekRectangle.

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

BarispertamamenghasilkansebuahobjekPointlalumembuatvariabelblankmengacu kepadanya.Bariskeduamengubahblanksehinggaketimbangmengacukepadasuatu objek,iajustrulebihmemilihuntuktidakmengacukepadaobjekmanapun(objeknull).

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.

Ketika Anda mendeklarasikan sebuah tipe data primitif, Anda akan

178

mendapatkan ruang penyimpanan untuk nilai primitif. Ketika Anda mendeklarasikan variabel bertipe data objek, Anda akan mendapatkan ruang memorisebagaiacuan(reference)kepadasebuahobjek.AgarobjekyangAnda buatmemilikiruang,Andaharusmenggunakanperintahnew.

JikaAndatidakmenginisialisasisebuahtipeprimitif,Javatelahmemberinilai bawaan(default)untuksetiaptipedatatersebut.Contohnya,0untuktipedataint dantrueuntuktipeboolean.Nilaibawaanuntuktipetipeobjekadalahnullyang berartitidakadaobjek.

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

Sebuah pencitraan (snapshot) atas kondisi/keadaan diagramstate yangterjadipadasebuahprogram,ditunjukkandengan gambar.

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

Bab9 MembuatObjekAndaSendiri 9.1 Definisidefinisikelasdantipetipeobjek

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

akanmelihatbeberapacontohdefinisidefinisikelasyangmampumenunjukkankepada kitatipeobjekbaruyangbermanfaat. Berikutiniadalahhalhalpentingyangharusdiperhatikandalambabini:

Mendefinisikan sebuah kelas baru akan menyebabkan 'lahirnya' sebuah tipe objekbarudengannamayangsama.

Suatudefinisiuntukkelasdapatdiasumsikansebagaisebuahcetakan(template) untukobjek:definisiiniakanmenentukanvariabelinstanmanayangdimiliki objeksekaligusmetodemetodeyangbisaberoperasidiatasnya.

Setiap objek merupakan milik beberapa objek sekaligus; oleh karena itulah, setiapobjekjugamerupakaninstandaribeberapakelas.

KetikaAnda menggunakanperintah new untuk membuat sebuahobjek, Java 188

memanggil sebuah metode khusus yang disebut constructor untuk menginisialisasivariabelvariabelinstan.

Semuametodeyangberoperasidalamsebuahtipeakanmasukdalamdefinisi kelasuntuktipetersebut.

Berikutinimerupakanisuisusintaksmengenaidefinisidefinisikelas:

Namakelas (atau tipeobjek)selalu dimulai denganhurufkapital yangakan membedakannyadengantipetipeprimitifdannamanamavariabel.

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:

Namakonstruktorharussamadengannamakelas. Konstruktortidakmempunyaitipedanataunilaipengembalian. Keywordstatictidakbolehdigunakan.

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.

Modifier: menggunakan objek sebagai argumen dan memodifikasi beberapa atausemuabagiandidalamnya.Seringkalimengembalikanvoid.

Fillinmethod:salahsatuargumennyaadalahsebuahobjek'kosong'yangdiisi olehmetode.Secarateknis,sebenarnyainimerupakansalahsatubentukdari modifier.

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

if(time1.minute<time2.minute)returnfalse; if(time1.second>time2.second)returntrue; returnfalse; }

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

while(time.minute>=60){ time.minute=60; time.hour+=1; } } Solusiinisudahtepat,tapitampaknyatidakterlaluefisien.BisakahAndamemberikan sebuahsolusiyangtidakmembutuhkanbentukbentukperulangan(iteration)?

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

} Kodediataslebihsingkatdaripadaversiaslinya.Selainitu,sayajugalebihmudah untukmenunjukkankepadaAndabahwametodeinimemangbenar(anggaplah,seperti biasa, bahwametodemetodeyangdipanggilnya jugabenar). Untuklatihan,cobalah menulisulangincrementdengancarayangsama.

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

Suatumetodeyangmengubahsatuataulebihobjekyang diterimanyasebagaiparameter,biasanyamengembalikanvoid. Suatujenismetodeyangmengambilsebuahobjekkosong

Fillinmethod

sebagaisebuahparameterlalumengisivariabelvariabel instannyaketimbangmembuatsuatunilaikembalian.Metode jenisinibiasanyabukanlahpilihanterbaikuntukdigunakan.

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

Kodeiniakanmembuatsebuaharrayyangdiisidengantigaelemenbertipedouble,lalu membuatduavariabelyangberbedamengacukepadanya.Situasiinimerupakansalah satubentukaliasing.

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

elemen).Adalahidebrilianuntukmenggunakannilaivariabelinstaninisebagaibatas atasuntuksebuahperulanganketimbangmenggunakannilaiyang konstan.Dengan variabelini,jikaukuranarraysuatuarraymengalamiperubahan,makaAndatidakperlu lagibersusahpayahmengubahsemuapernyataanyangterkaitdenganperulangan;ini akanbekerjadanberfungsiuntuksemuukuranarray. for(inti=0;i<a.length;i++){ b[i]=a[i]; }

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

int[]a=newint[n]; for(inti=0;i<a.length;i++){ a[i]=randomInt(0,100); } returna; } Tipekembaliannyaadalahint[],yangberartibahwametodeiniakanmengembalikan nilainilaibertipeinteger.Untukmengujimetodeini,Andasebaiknyamenulismetode lainyangdapatmencetakisiarraytersebut.


publicstaticvoidprintArray(int[]a){

for(inti=0;i<a.length;i++){ System.out.println(a[i]); } } Kodeberikutiniakanmembuatsebuaharraylalumencetakhasilnya: intnumValues=8; int[]array=randomArray(numValues); printArray(array); Dimesinsaya,hasilnyaadalah: 27 6 54 62 54 224

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

int[]counts=newint[100]; for(inti=0;i<scores.length;i++){ intindex=scores[i]; counts[index]++; }

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

Sebuahprogramyangmengerjakanhalhalyangsamasetiap kalidigunakan/dipanggil. Suatuderetanangkaangkayangtampaksepertiangkaangka

pseudorandom

yangdiacak,tetapisebenarnyatidak.Angkaangkatersebut hanyalahhasildarikomputasiyangdeterminis. Array bertipe integer dimana setiap nilai integer akan

histogram

mencacah banyak nilai yang masuk ke dalam interval intervalyangsudahditentukan.

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

Bab11 ArrayberisiObjek 11.1 Komposisi


Sejauh ini kita telah melihat beberapa contoh komposisi (kemampuan untuk mengombinasikan fiturfitur bahasa dalam beberapa variasi susunan). Salah satunya adalahdenganmenggunakanpemanggilanmetodesebagaibagiandariekspresi.Contoh lainnyaadalahstrukturpernyataantersarang;Andadapatmeletakkanpernyataan if di dalamperulanganwhile,ataudidalampernyataaniflainnya,dst. Setelahmelihatpolaini,dansetelahbelajarmengenaiarraydanobjek,Andasemestinya tidakperluterkejutketikamengetahuibahwaternyataAndabolehmemilikiarrayberisi objek.Kenyataannya,Andajugadapatmemilikisebuahobjekyangberisiarrayarray (sebagaivariabelinstan);Andabolehmemilikiarrayyangmengandungarray;Anda jugabolehmemilikiobjekyangmengandungobjek,dsb. Di dua bab berikutnya, kita akan melihat beberapa contoh komposisi. Diantaranya adalahobjekCard.

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",

Pengaruhyangdihasilkanolehpernyataandiatasakansamadenganyangditimbulkan olehdeklarasi,alokasidanassignmentsecaraterpisah.Diagramkeadaandariarrayini akantampaksepertigambarberikut:

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] ); }

Ekspresisuits[c.suit]artinyaadalahgunakanvariabelinstansuitdariobjekcsebagai sebuahindekskedalamarraydengannama suits,lalupilihstringyangadadisitu. hasildarikodeberikut Cardcard=newCard(1,11); printCard(card); adalahJackofDiamonds.

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); }

Sekarangjikakitamembuatduaobjekyangberbedayangberisidatayangsama,kita bisa menggunakan metode sameCard untuk melihat apakah keduanya

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.");

Jadi,persyaratan(condition)didalamkodediatasbernilai True.Bagaimanabentuk diagramkeadaanketikacard1==card2bernilaiTrue? Dibagian7.10sayamengatakanbahwaAndasebaiknyajanganpernahmenggunakan operator==dalamStringkarenaoperatorinisebenarnyatidakmengerjakanapayang Andaharapkan.KetimbangmembandingkanisiString(deepequality),kitalebihbaik memeriksaapakahkeduaStringmerupakanobjekyangsama(shallowequality)ataukah tidak.

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;

JikakeduapernyataandiatastidakadayangbernilaiTrue,makakelompokkelompok kartutersebuttentunyabernilaisama.Jikainiyangterjadi,kitaharusmembandingkan peringkatnya: if(c1.rank>c2.rank)return1; if(c1.rank<c2.rank)return1;

JikakeduapernyataandiatasjugatidakbernilaiTrue,makaperingkatnyatentusama, jadikitaakanmengembalikannilai0.Dalammodelpemeringkatansepertiini,kartuAs 247

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

Bab12 ObjekberisiArray 12.1 KelasDeck


Dalam bab sebelumnya, kita sudah bekerja dengan sebuah array yang berisi objek, tetapi saya juga menyebutkan bahwa kita juga berkesempatan memiliki objek yang berisisebuaharraysebagaisebuahvariabelinstan.Dalambabinikitaakanmembuat sebuah objekbaru,yakni Deck,yangberisisebuaharrayyangberisi Card sebagai variabelinstannya. Definisikelasnyatampaksebagaiberikut: classDeck{ Card[]cards; publicDeck(intn){ cards=newCard[n]; } }

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.

SayatidakmenyarankanAndauntukmenggunakankonsepaliasingkarenaperubahan yangterjadipadasatusubtumpukanakanlangsungmemengaruhisubtumpukanlain. Kecualikalauobjekobjekyangakandikenai aliasing tersebutmerupakanobjekyang tidakbisadiubah(immutable).Dalamkasusini,kitatidakbisamengubahperingkatatau kelompoksebuahkartu.Sebaliknya,kitajustruakanmembuatsetiapkartusatukalisaja lalumemperlakukannyasebagaiobjekyangimmutable.Denganalasanini,penggunaan aliasinguntukCardmerupakankeputusanyangmasihrelevan.

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

Bab13 PemrogramanBerorientasiObjek 13.1 BahasaPemrogramandanTekniktekniknya


Adabegitubanyakbahasapemrogramandiduniaini,begitujugadenganteknikteknik pemrograman (sering disebut sebagai paradigma). Tiga teknik yang sudah muncul dalambukuiniantaralain;prosedural,fungsional,danobjectoriented.MeskipunJava seringdisebutsebutsebagaibahasapemrogramanberorientasiobjek,tapikitamasih diperkenankan untuk menulis program dengan teknik mana pun. Teknik yang saya peragakandisinitermasukteknikprosedural.ProgramprogramJavayangsudahada beserta paketpaket bawaan Java ditulis menggunakan gabungan dari ketiga teknik tersebut.Bedanya,programprogramdanpaketpakettersebutlebihcenderungditulis menggunakanparadigmapemrogramanberorientasiobjek. Bukanperkaramudahuntukmendefinisikanartidaripemrogramanberorientasiobjek, namun beberapa poin berikut ini bisa Anda jadikan pegangan untuk melihat karakteristiknya:

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

menjadiobjekterkini(thecurrentobject).Didalammetodeini,Andabisamengacuke variabelinstanmilikobjekterkinimenggunakannamanya,tanpaharusmenulisnama objektersebutsecaraspesifik. Selainitu,Andajugabisamengacukeobjekterkinimenggunakankatakuncithis.Kita sebelumnyatelahmelihat this digunakandidalamkonstruktor.Faktanya,Andabisa sajamenganggapkonstruktorkonstruktorsebagaimetodeobjekyangbersifatkhusus.

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 ); }

Tapiituhanyaakanmenambahpanjangkodeini,ketimbangmembuatnyatampaklebih ringkas.Untukmemanggilmetodeini,kitabisamemanggilnyamelaluisebuahobjek, sebagaicontoh:


Compl exy =n ewC ompl ex( 3.0, 4.0 ); doubl ere sult =y .abs ();

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();

atauAndajugabisamemanggilnyalangsungmelaluiprintln: System.out.println(x); Dalamkasusini,outputnyaadalah1.0+2.0i. VersitoStringinimasihbelumcukupbaikjikabilanganimajinernyabernilainegatif. Sebagailatihan,buatlahsebuahversiyanglebihbaik:

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

Darihasilkonvensi,metodeiniakanselalumenjadimetodeobjekyangmengembalikan nilaibertipeboolean. DokumentasiuntukequalsdidalamkelasObjectmemberikanbeberapapanduanyang harusAndaterapkanketikaAndainginmembuatdefinisipersamaanAndasendiri: Metodeequalsmengimplementasikansebuahrelasiekuivalensi:


Refleksif:untuksetiapnilaiyangdiacux,x.equals(x)harusbernilaitrue. Simetris:untuksetiapnilaiyangdiacuxdany,x.equals(y)harusbernilaitrue jikadanhanyajikay.equals(x)jugabernilaitrue.

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.

Definisiequals yangsayaberikansudahmemenuhisemuapersyaratandiataskecuali satu.Yangmana?Sebagailatihan,cobaperbaiki!

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

ini;kelasdanobjek.Tipemanayanglebihjelas(secaraumum)?Caramanayang lebihalamiuntukmengekspresikankomputasi(atau,agarlebihadildanjelas,tipe komputasisepertiapayangbisadiekspresikanpalingbaikmenggunakanmasing masingbentuk)?

297

Bab14 LinkedList 14.1 AcuanacuandalamObjek


Di dalambabsebelumnyakitasudahmelihatbahwavariabelvariabelinstansebuah objekdapatberupaarraydanataujugaobjek. Satukemungkinanyangpalingmenarikadalahbahwasebuahobjekbisaberisisebuah acuanyangmengacukeobjeklainyangsamatipenya.Adasebuahstrukturdatayang akanmengambilmanfaatbesardarifiturini;list. Listterbuatdaridarikumpulannodeyangdalamsetiapnodenyaberisisuatuacuanke nodeberikutnyadalamlist.Selainitu,setiapnodebiasanyaberisisatuunitdatayang disebutcargo.Dalamcontohpertamakita,kargoiniberupaintegertunggal.Namundi kesempatanberikutnyakitaakanmenulissebuahlist generic yangdapatmenyimpan objekdaritipeapapun.

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:

Sekarangkitasemuasudahtahucaramembuatnodenodesekaligusbagaimanacara menghubungkannyaagarmenjadilist.Apayangmungkinkurangjelassampaisaatini 300

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

tapiadalahhalsebaliknyauntukmemanggilsebuahmetodeobjekmelaluiobjeknull. Nodenode=null; printList(node);//legal node.printList();//NullPointerException Pembatasaninijustrumembuatkitaakantampakanehketikahendakmenuliskode pemanipulasilistyangbersihdalamparadigmaberorientasiobjek.Tapinanti,kitaakan melihatcarauntukmenyelesaikanmasalahini.

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.

Apayangakanterjadijikamemanggilmetodeinilalumelewatkansebuahlistyang hanyaberisisatuelemen(satusingleton)?Apayangterjadijikamelewatkanlistkosong sebagaisebuahargumen?Adakahpreconditionuntukmetodeini?

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

Bab15 Stacks 15.1 TipeDataAbstrak


Semuatipedatayangtelahkitalihatsejauhinimerupakantipedatakonkret.Artinya, kita harus menentukan, dengan lengkap, bagaimana tipe datatipe data tersebut diimplementasikan. Sebagai contoh, kelas Card merepresentasikan sebuah kartu menggunakan dua integer. Sebagaimana yang telah saya kemukakan sebelumnya, teknik di atas bukanlah satusatunya cara untuk merepresentasikan sebuah kartu; sebenarnyamasihbanyakcaralainuntukmengimplementasikannya. Abstract Data Type (Tipe Data Abstrak), atau ADT, merupakan suatu kumpulan operasi (atau metode) dan bentuk semantik dari operasioperasi tersebut (apa yang dilakukan oleh operasi) tapi dia tidak menentukan implementasi operasioperasi itu sendiri.Halinilahyangmembuatmerekaabstrak. KenapaADTberguna?

ADT menyederhanakan tugas Anda ketika hendak menentukan sebuah algoritmajikaAndabisamengidentifikasioperasioperasiyangAndabutuhkan tanpaharusberpikirpadasaatyangbersamaanmengenaibagaimanaoperasi operasitersebutakandikerjakan.

KarenaadabanyakalternatifcarauntukmengimplementasikanADT,mungkin akanbergunabagikitauntukmenulissebuahalgoritmayangbisadigunakan untukbeberapaimplementasisekaligus.

Varianvarian ADT yang sudah populer, seperti Stack ADT dalam bab ini, seringdiimplementasikandidalampustakastandar(standardlibrary)sehingga

316

merekabisaditulissekalidanlangsungdigunakanolehbanyakprogrammer.

Operasioperasi ADT menyediakan sebuah level bahasa tingkattinggi yang umumdigunakanuntukmemilih,menentukan,danmembahassuatualgoritma.

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

pembungkusketipeprimitifyangberbedabeda.Andaharusmemeriksadokumentasi untukmasingmasingkelaspembungkusuntukmelihatapasajayangbisadiubahdan apayangtidak.

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);

Karena parseInt merupakansebuahmetodekelas,Andamemanggilnyadengancara menyebutkannamakelasdanmetodenyamemakainotasidot. Basis6mungkintidakterlaluberguna,tetapiheksadesimal(basis16)danoktaf(basis 8)merupakansesuatuyangsangatseringdipakaidalamduniailmukomputer.

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.

Jikatermnyaberupaoperan,masukkan(push)diakedalamstack. Jikatermnyaberupaoperator,ambil(pop)operanoperantersebutdari dalamstack,kerjakanoperasiuntukmereka,lalumasukkanhasilnyake dalamstacklagi.

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

four tokens. Untukmenguraikanekspresiekspresi,kitamemilikiopsiuntukmenentukankarakter tambahanyangakankitagunakansebagaidelimiter. StringTokenizer st = new StringTokenizer ("11

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

22+33*","+*/",true); Argumenketigaberkata,Ya,kamiinginmemperlakukandelimiterdelimitersebagai tokentoken.sekaranghasilnyaadalah 11 22 + 33 326

* 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(); } }

Oke,kelihatannyasudahlebihjelaskeltimbangsebelumnya!KarenaQueuemerupakan perluasan(anak)dari LinkedList,kitaakanmewarisikonstruktornya,yakni isEmpty 339

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

menemukanelementerakhiragarkitabisamembuatnyamengacukenodeyangbaru. Penelusuraninimenghabiskanwaktuyangsesuaidenganpanjanglist.Karenaruntime merupakanfungsilineardaripanjang,kitabisamengatakanbahwametodeinitermasuk lineartime.Dibandingkandenganconstanttime,lineartimebisadikategorikansebagai yangburuksekali.

16.3 LinkedQueue
KitamenginginkansebuahimplementasidariADTAntrianyangbisamelakukansemua operasidalamwaktuyangkonstan.Salahsatucarauntukmenyelesaikanmasalahini adalahdenganmengimplementasikanlinkedqueue.Carainibisadibilangsamadengan linkedlistkarenaiaterdiridariobjekobjek Node yangsalingterhubung,mulaidari yangberjumlah0(tanpa Node)ataulebihdariitu.Perbedaannyaadalahbahwasuatu antrianmemeliharaacuanyangberasaldarinodepertamadanterakhir,sepertitampak dalamgambar.

InilahtampilanimplementasilinkedQueue: publicclassQueue{ publicNodefirst,last; publicQueue(){ first=null; last=null;

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; } }

Syaratpertamamemeriksadanmemastikanbahwalastsudahmengacukesebuahnode; jikaya,makakitaharusmembuatnyamengacukenodeyangbaru. Syaratyangkeduaberurusandengankasuskhususdimanalistpadaawalnyamemang berstatuskosong.Dalamkasusini,baikfirstmaupunlastmengacukenodeyangbaru. Metoderemovejugaberurusandenganbeberapakasuskhusus. 344

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

Metode add terlihatseperti push disubbab15.12;iameletakkanitembarukedalam ruangkosongdibagianberikutnyalalumenaikkannilaiindeksnya. Implementasiremovesamasaja.Metodeinimengambilitempertamadariantrianlalu menaikkanfirstsehinggaiamengacukekepalabarumilikantrian.Gambarberikutini menunjukkansepertiapatampilanantrianketikakeduaitemsudahdihapus.

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

} addsamadenganpush: publicvoidadd(Comparableitem){ if(index==array.length){ resize(); } array[index]=item; index++; }

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){

//move the lastitem into the empty slot index ;

354

array[maxIndex return result; }

]= 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

constanttime lineartime linkedqueue

Operasi yang memiliki runtime yang tidak bergantung kepadaukuranstrukturdatanya. Operasiyangruntimenyaberupafungsilineardariukuran strukturdatanya. Implementasiantrianmenggunakanlinkedlistdanacuanke nodepertamadanterakhir. Implementasi antrian menggunakan array dan indeks dari

circularbuffer

elemenpertamadanruangkosongyangadadisebelahnya (nextavailablespace). Kumpulan kelaskelas. Spesifikasi metaclass berisi

metaclass

persyaratanpersyaratan yang harus dipenuhi oleh suatu kelasagarbisadimasukkankedalamkumpulan.

interface

Istilah Java untuk menyebut metaclass. Jangan sampai dibingungkandenganartikatainterfaceyanglebihluas.

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

harusmenjadianggotaComparable,danlistnyatersusundalamurutanterbalik. TulislahsebuahmetodeobjekadduntukSortedListyangmenggunakanComparable sebagaiparameterdanmampumenambahkanobjekbarukedalamlist,padalokasiyang tepatsehinggalistnyatetapberadadalamposisiterurut. JikaAndamau,AndabisamenulissatumetodehelperdalamkelasNode.

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

Bab17 Pohon(Trees) 17.1 SimpulPohon


Laiknyalist,pohonterdiridarisimpulsimpul.Salahsatupohonyangpalingbanyak dikenaladalahpohonbiner(binarytree).Setiapsimpulpohoniniberisisebuahacuan yang mengacu ke dua simpul lainnya (kemungkinan null). Definisi kelasnya akan tampaksebagaiberikut: publicclassTree{ Objectcargo; Treeleft,right; } Sepertisimpulsimpuldalamlist,simpulsimpulpohonjugaberisikargo:dalamhalini berupa Object yanggenerik.Variabelvariabelinstanlainnyadinamai left dan right, yangsesuaidenganstandarmatakitaketikadirepresentasikanmenggunakangambar:

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

Awalnyakitaakanmengalokasikantempatuntuksimpulsimpulanakterlebihdahulu: Treeleft=newTree(newInteger(2),null,null); Treeright=newTree(newInteger(3),null,null); Kitabisamembuatsimpulinduklalumengaitkannyakesimpulanakpadasaatyang bersamaan: Treetree=newTree(newInteger(1),left,right); Kodeinimenghasilkankeadaansepertiyangditunjukkanpadagambarsebelumnya.

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?

Latihan17.4 Tinggisebuahpohonadalahjalurterpanjangdariakarkedaunmanapun.Tinggibisa didefinisikansecararekursifse[ertiberikut:


Tinggidaripohonyangnulladalah0. Tinggidaripohonyangtidaknulladalah1+max(leftHeight,rightHeight),di mana leftHeight adalahtinggidarisimpulanaksebelahkiridan rightHeight adalahtinggidarisimpulanaksebelahkanan.

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

Bab18 Heap 18.1 ImplementasiPohonmenggunakanArray


Apa yang dimaksud dengan mengimplementasikan pohon? Sejauh ini kita hanya melihatsatuimplementasipohonyangmenggunakanlinkedlist.Tetapisebenarnyaada struktur lain yang bisa kita identifikasi sebagai pohon. Dan segala hal yang bisa melakukanoperasipohondasarbisadisebutsebagaipohon.

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

Adaimplementasipohonlainyangmenggunakanarraydanindekssebagaigantiobjek danreferensi.Untukmelihatbagaimanaiabekerja,kitaakanmemulaidenganmelihat implementasicampuranyangmenggunakanarraydanobjek.

Gambardibawahinimemperlihatkansebuahpohonsepertisebelumnyayangpernah kitalihat.Padasisikananadasebuaharraydarireferensiyangmengacupadamuatan darisebuahsimpul.

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!

Karenakitatidakmenggunakanreferensi,berartiapayangdigunakansekaranghanya objekmuatandantidakadayanglain.Sehinggakitabisamengimplementasikanpohon sebagaisebuaharraydariobjekmuatan. 385

Dibawahinicontohimplementasipohonmenggunakanarray: publicclassArrayTree{ Object[]array; intsize; publicArrayTree(){ array=newObject[128]; } Sejauhinitidakadayangbaru.Satusatunyavariabelinstansadalaharraydariobjek yangberisimuatanpohon.Konstruktormenginisialisasiarraydengankapasitastertentu; Hasilnyaadalahsebuahpohonkosong.

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.

Padasisilain,implementasidenganarrayhematdalamhalruangpenyimpanan,karena tidakadanyahubunganantarasimpul,danadabeberapaoperasiyanglebihmudahdan cepatjikapohondiimplementasikandenganarray.

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:

//findtheindexofthelowestitembetween //iandtheendofthearray findLowest(array,i){ //lowestcontainstheindexofthelowestitemsofar lowest=i; for(intj=i+1;j<array.length;j++){ //comparethejthitemtothelowestitemsofar

390

//ifthejthitemislower,replacelowestwithj } returnlowest; }

swap(i,j){ //storeareferencetotheithcardintemp //maketheithelementofthearrayrefertothejthcard //makethejthelementofthearrayrefertotemp }

Untukmenganalisakinerjaalgoritmaini,langkahpertamaadalahmenentukanoperasi apayangakandihitung.Seyogyanyaprogrammelakukanbanyakhalseperti:menambah i,membandingkannyadenganpanjang deck, mencarielementerbesarpadaarray,dan lainlain.Sehinggatidaklahterlalujelashalmanayangakandihitung.

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.

Jadijumlahperbandingantotaladalah1+2+...+n1.Jumlahaninisamadengann 2/2 n/2.Untukmenjelaskanalgoritmaini,kitaakanmengabaikann/2danmenganggaptotal perbandinganadalahn2.

18.3AnalisisMergeSort

Padabagian12.6sayamengklaimbahwamergesortmembutuhkanwaktunlogn,tetapi sayatidakmenjelaskanbagaimanaataumengapa.Sekarangsayaakanmenjelaskannya. Kembali,kitamulaidenganmelihatpseudocodealgoritma. mergeSort(array){ //findthemidpointofthearray //dividethearrayintotwohalves //sortthehalvesrecursively //mergethetwohalvesandreturntheresult }

392

Padasetiaplevelrekursi.Kitamembagiarraydalamduabagian,memanggilduametode rekursif,dankemudianmenggabungkannya.Secaragrafis,prosesnyaadalahsebagai berikut:

Setiapbarispadadiagramadalahtingkatrekursi.Padabaristeratas,arraytunggaldibagi menjadiduabagian.Padabarispalingbawah,narraydengansatuelementiapbagian digabungmenjadin/2arraydenganduaelemensetiapbagian.

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

konstantiapelemen,waktusebandingdenganjumlahitem.Itulahmengapa,menghapus sesuatudariarraydanmenambahkansesuatupadalistkeduanyamenggunakanwaktu yangkonstan.

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,

Pohonkosongselaludianggapkomplit.Kitabisamendefinisikancompletenesslebih dalamdenganmembandingkantinggisubpohon.Daripelajaransebelumnyakitaketahui bahwatinggipohonadalahbanyaktingkatanyangada. 397

Dimulaidariakar,jikapohonkomplit,lalutinggisubpohonkiridantinggisubpohon kananharussama,atausubpohonkiribisalebihtinggisatu.Padakasuslain,pohon tidakdisebutkomplit.Dengandemikianjikapohonkomplit,makahubunganantara subpohonharusselalubenaruntuksetiapsimpulpadapohon.

Sifatheapadalahrekursif.Agarpohondisebutheap,nilaiterbesarpadapohonharus adapadaakar,danhalyangsamaharusbenarpadasetiapsubpohon. Latihan18.1Tulismetodeyangmengambilpohonsebagaiparameterdanmengecek apakahkomplitatautidak. Petunjuk:Andadapatmenggunakanmetodeheightdarilatihan17.4 Latihan18.2Tulismetodeyangmengambilpohonsebagaiparameterdanmengecek apakahiamemilikisifatheap.

18.7Penghapusanpadaheap
Mungkinkelihatanganjilkitaakanmenghapussesuatudariheapsebelummenambah apapun,tetapisayapikirpenghapusanlebihmudahuntukdijelaskan.Sekilas,kita mungkinberpikirmengapusitemdariheapadalahoperasiyangkonstan,karenaitem denganprioritastertinggiselaluberadapadaakar.Masalahnyaadalahsetiapkita menghapussimpulakar,kitaditinggalkansesuatuyangbukanlagiheap.Sebelumkita dapatmengembalikanhasilnya,kitaharusmempebaikisifatheap.Kitamenyebut operasiinireheapify. Situasiinidigambarkanpadagambarberikut:

398

Simpulakarmemilikiprioritasrdanduasubpohon,AdanB.nilaipadaakarsubpohon AadalahadannilaipadasubpohonBadalahb.

Kitamengasumsikansebelumkitamenghapusrdaripohon,pohonadalahheap.Ini mengakibatkanradalahnilaiterbesardalamheapdanbahwaadanbadalahnilai terbesardalamsubpohonmereka.Ketikakitamenghapusr,kitaharusmembuatpohon yangdihasilkankembalimenjadiheap.Dengankatalainkitabutuhmeyakinkania memilikisifatcompletenessdanheapness.

Caraterbaikuntukmenjamincompletenessadalahdenganmenghapuselemenpaling bawah,yangpalingkanan,yangkitasebutcdanmeletakkannilainyapadaakar.Pada implementasipohon,kitaharusmenjelajahipohonuntukmencarisimpulini,tetapipada implementasiarray,kitadapatmencarinyapadawaktukonstankarenaiaakanselalu elemennonnullterakhirpadaarray.

Tentu,nilaiterakhirbukanyangtertinggi,jadimeletakkanyyapadaakarakanmerusak sifatheapness.Untungnyamudahuntukdiperbaiki.Kitatahubahwanilaiterbesar 399

dalamheapsetelahrdihapusadalahaataub.Itulahmengapakitabisamemilihyang manayanglebihbesardanmenggantinyadengannilaipadaakar.

Marikitaanggapbadalahyangterbesar.Karenakitatahuiaadalahnilaitertinggipada kiriheap,kitabisameletakkannyapadaakardanmeletakkancpadapuncaksubpohon B.Sekarangsituasinyaakansepertidibawahini:

lagi,cadalahnilaiyangkitakopidarielementerakhirdalamarraydanbadalahnilai tertinggidalamheap.KarenakitatahukitatidakpernahmenggantisubpohonA,kita mengetahuiiamasihmerupakanheap.Satusatunyamasalahadalahkitatidakdapat mengetahuiapakahsubpohonBadalahheap,karenakitahanyamenempelsebuahnilai (kemungkinanrendah)padaakarnya. AkanlebihbaikjikakitamemilikimetodeyangbisareheapifysubpohonB? Tunggu....kitapunya

18.8PenambahanHeap
Menambahkansebuahitembarupadaheapadalahoperasiyangmiripdengan penghapusanheap,perbedaanyabahwakitatidakmenghamburkanelemendariatas 400

tetapikitamenghamburkanelemenkeatasdaribawahheap.

Untukmenjaminsifatcompleteness,kitamenambahelemenbarupadaelemenpaling bawahpadapohon,yangmerupakanruangkosongberikutnyapadaarray.Laluuntuk mengembalikansifatheap,kitamembandingkannilaibarudengantetangganya.Situasi nyaakanterlihatsepertiini:

Nilaibaruadalahc.Kitabisamengembalikansifatheappadasubpohoninidengan membandingkancdengana.Jikaclebihkecil,makasifatheaptelahdipenuhi.Jikac lebihbesarmakakitamengganticdana.Prosesswapakanmemenuhisifatheapkarena kitatahucharuslebihbesardarib,karenac>adana>b.

Sekarangsubtreetelahmenjadiheapkembali,selanjutnyaprosesdilanjutkankesimpul atas(aatauc)denganmembandingkandenganorangtuanyademikianseterusnya sampaimencapaiakar.

18.9KinerjaHeap
Untukpenambahandanpenghapusan,kitamenggunakanoperasidenganwaktu yangkonstanuntukpenambahandanpenghapusanyangsebenarnya,tetapikemudian kitaharusmelakukanreheapifypadapohon.Padasatukasuskitamulaidariakardan

401

dilanjutkankebawah,membandingkanelemendansecararekursifmelakukan reheapifypadasubpohon.Padakasuslainkitamulaipadadaundanbekerjakeatas, kembalikitamembandingkanelemenpadatiaplevelpadapohon.

Sepertibiasa,adabeberapaoperasiyangakankitahitung,sepertipembandingandan pertukaran.Keduapilihanakanbekerja;masalahsebenarnyaadalahbanyaklevelpada pohonyangkitaperiksadanberapabanyakusahayangkitalakukansetiaplevel.Pada keduakasuskitatetapbekerjapadasebuahlevelpohonsampaikitamengembalikan sifatheap,yangberartikitamungkinhanyaberkunjungsekali,ataupadakasusterburuk kitaharusmengunjungisemuaelemen,sekarangmarikitalihatpadakasusterburuk.

Padasetiaplevel,kitamelakukanhanyaoperasidenganwaktuyangkonstanseperti pembandingandanpenggantian.Jaditotalkerjasebandingdenganbanyaktingkatan padapohon,dengankatalaintinggi.Jadikitabisaberkataoperasioperasiini berbandinglurusdengatinggipohon,tetapiukuranmasalahyangmenarikbukan tingginya,tetapibanyakelemenpadaheap.

Dalamfungsin,tinggipohonadalahlog2n.Initidakselalubenaruntuksemuapohon, tetapihanyabenaruntukpohonyanglengkap.Untukmengetahuikenapa,pikirkan banyaksimpulpadasetiapleveldaripohon.Levelpertamaberisi1,level2berisi2, levelketigaberisi4,demikianseterusnya.Levelkeiakanberisi2isimpuldanjumlah elemendisemualevelsampaiiadalah2i1.Dengankatalain2h=n,yangberarti h=log2n.

Sehingga,keduanyapenambahandanpenghapusanmenggunakanwaktuyang logaritmik.Untukmenambahdanmenghapusnelemenmakaakanmenggunakanwaktu 402

nlog2n.

18.10Heapsort
Hasildaribagianyanglalubisamenjadiinspirasiuntukalgoritmapengurutan.Terdapat nelemen,kitamenambahkanmerekakedalamHeapkemudianmenghapusnya.Karena sifatheap,merekaakankeluardalamkeadaanterurut.Kitatelahmemperlihatkan algoritmaini,yangdisebutheapsort,iamenggunakanwaktusebandingdengannlog2n, yanglebihbaikdariselectionsortdansamadenganmergesort.

Semakinbesarnilai,kitaberharapheapsortakanlebihcepatdariselectionsort,tetapi analisiskinerjatidakmenunjukkancarauntukmengetahuiapakahiaakanlebihcepat darimergesort.Kitaakanberkatakeduaalgoritmamemilikiorderofgrowthyangsama karenawaktukinerjamerekabertambahdenganbentukfungsiyangsama.Caralain untukmengatakanhalyangsamaadalahmerekamemilikikompleksitasyangsama.

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

Sejauhinitidakadaalgoritmayangtelahkitalihatmemilikikompleksitaseksponensial. Untuknilainyangbesar,algoritmainicepatmenjaditidakpraktis.Namundemikian frasepertumbuhaneksponensialmuncullebihseringbahkanpadabahasayangtidak teknis.Iaseringdigunakantidaktepatjadisayainginmemasukkanartiteknisnya. Orangseringmenggunakaneksponensialuntukmenjelaskankurvayangbertambahdan berakselerasi(kurvayangmemilikikemiringanpositifdanlekukan).Tentusajaada banyakkurvalianyangsesuaidenganpenjekasanini,termasukfungsikuadrat(dan polinomilaltingkatyanglebihtinggi)danbahkanfungsisepertinlogn.Sebagianbesar kurvainitidakmemiliki(bahkanmerusak)sifateksplosifdarieksponensial.

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

Latihan18.7 TulisimplementasidariHeapberdasarkanimplementasipohondenganarray.Waktu eksekusiadddanremoveharussebandingdenganlogn,dimannadalahbanyakelemen dalamheap.

406

BAB19 Maps 19.1Array,Vector,Map


Arrayadalahstrukturdatayangsecaraumumsangatberguna,tetapiarray memilikiduaketerbatasanutamayaitu:

Ukuranarraytidakbergantungterhadapjumlahelemenyangadadidalamnya. Jikaarraylebihbesardibandingjumlahelemendidalamnyamakaakan menghabiskantempat.Sedangkanjikaterlalukecil(Ukuranarraylebihkecil) makakemungkinandapatmenyebabkankesalahan.Ataukitaharusmenulis kodeuntukmengubahukurannya.

Meskipunarraydapatberisitipeapapun,indeksarrayharusbertipeinteger. KitatidakdapatmisalnyamenggunakanStringuntukdigunakansebagaiindeks.

Padabab17.9kitatelahmelihatbagaimanakelasVectoryangmerupakankelasyang disediakanolehJavabisamenyelesaikanmasalahpertama.Ketikasebuahkode menambahelemen,makaVectorakanmembesarsecaraotomatis.Danjuga memungkinkanuntukmemperkecilVectorsehinggakapasitasnyasamadenganjumlah elemenyangadadidalamnya.

TetapiVectortidakdapatmenolongpadamasalahkedua.IndeksVectormasihharus bertipeinteger.MasalahinibisadiselesaikandenganstrukturdataMapADT.Map serupadenganVector,perbedaannyaadalahMapdapatmenggunakantipeobjekapapun sebagaiindeks.IndekspadaMapdisebutsebagaikunci.

407

SebagaimanaandamenggunakanindeksuntukmengaksesnilaipadaVector,andajuga menggunakankunciuntukmengaksesnilaipadaMap.Setiapkuncidiasosiasikan dengansebuahnilai,itulahmengapaMapkadangkadangdisebutarrayassosiatif. Assosiasiantarasebuahkuncidengansebuahnilaidisebutentri.

ContohumumdaristrukturdataMapadalahkamus,yangmemetakankatakata(kunci) padadefinisinya(nilai).KarenahaliniMapjugakadangdisebutkamus.

19.2MapADT

SepertiADTlainyangtelahkitalihat,Mapsdidefinisikandenganhimpunanoperasi yaitu: contructor:MembuatsebuahMapkosong put:Menciptakansebuahentriyangmengasosiasikansebuahnilaidengansebuahkunci get:Untuksebuahkunciyangdiberikan,carinilaiyangbersesuaian containsKey:MengembalikantruejikaterdapatentripadaMapdengankunciyang diberikan keySet:MengembalikanstrukturdataSetyangberisisemuakuncipadaMap

19.3HashMapbuiltin
JavamenyediakanimplementasidariMapADTpadapaketjava.util.HashMap. SelanjutnyapadababinikitaakanlihatmengapadisebutHashMap

408

UntukmendemonstrasikanpenggunaanHashMapkitaakanmenulissebuahprogram sederhanayangmenjelajahisebuahStringdanmenghitungjumlahkemunculansuatu kata.

KitaakanmembuatkelasbaruyaituWordCountyangakanmembangunMapdan mencetakisinya.SetiapWordCountberisiHashMapsebagaivariabelinstance.

publicclassWordCount{ HashMapMap;

publicWordCount(){ Map=newHashMap(); } }

MetodepublikpadaWordCountadalahprocessLine,yangmengambilsebuahString danmenambahkatakatanyapadaMap,danprint,yangbertugasmencetakhasil pemrosesan.

ProcessLinememecahStringmenjadikatakatamenggunakanStringTokenizer(untuk mennggunakanStringTokenizerandaharusmengimpornyaterlebihdahulu,dengan menambahkanbarisimportjava.util.*sebelumdeklarasiclass)danmelewatkansetiap katapadaprocessWord.

publicvoidprocessLine(Strings){

409

StringTokenizerst=newStringTokenizer(s,,.); while(st.hasMoreTokens()){ Stringword=st.nextToken(); processWord(word.toLowerCase()); } }

publicvoidprocessWord(Stringword){ if(Map.containskunci(word)){ integeri=(integer)Map.get(word); integerj=newinteger(i.intValue()+1); Map.put(word,j); }else{ Map.put(word,newinteger(1)); } }

JikakatatelahadadalamMap,makakitamengambilvariabelpencacahnya, menambahkansatu,danmemasukkannya(put)kembalipadaMap.Jikatidak,kita hanyaakanmenaruhentribarupadaMapdenganpencacahdiberinilaisatu.

UntukmencetaksemuaentripadaMap,kitaharusbisamenjelajahiseluruhkuncidalam Map.Untungnya,HashMapmenyediakanmetodekeySet,yangmengembalikansebuah objekSet,danSetmenyediakansebuahmetodeiteratoryangmengembalikanobjek Iterator.

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+"}"); } }

SetiapelemenpadaiteratoradalahsebuahObjek,tetapikarenakitatahubahwamereka adalahkunci,kitabisamengcastingnyamenjadiString.Ketikakitamengambilsebuah nilaipadaMap,merekajugabertipeObjek,tetapikitatahubahwamerekaadalah pencacah,jadikitabisamengcastingnyamenjadibertipeinteger.

Berikutinicarauntukmenghitungkatakatapadasebuahkalimat:

WordCountwc=newWordCount(); wc.processLine("youspinmerightroundbaby"+ "rightroundlikearecordbaby"+ "rightroundroundround"); wc.print();

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.*;

publicclassWordCount{ HashMapMap; publicWordCount(){ Map=newHashMap(); }

publicvoidprocessLine(Strings){ StringTokenizerst=newStringTokenizer(s,",.");

412

while(st.hasMoreTokens()){ Stringword=st.nextToken(); processWord(word.toLowerCase()); } }

publicvoidprocessWord(Stringword){ if(Map.containsKey(word)){ integeri=(integer)Map.get(word); integerj=newinteger(i.intValue()+1); Map.put(word,j); }else{ Map.put(word,newinteger(1)); } }

publicvoidprint(){ Setset=Map.keySet(); Iteratorit=set.iterator(); while(it.hasNext()){ Stringkunci=(String)it.next(); integervalue=(integer)Map.get(kunci); System.out.println("{"+kunci+","+value+"}"); } }

publicstaticvoidmain(String[]args){ WordCountwc=newWordCount();

413

wc.processLine("youspinmerightroundbaby"+ "rightroundlikearecordbaby"+ "rightroundroundround"); wc.print(); } }

19.4ImplementasiDenganVector
CarayangmudahuntukmengimplementasikanMapADTadalahmenggunakanentri denganstrukturdataVector,dimanasetiapentriadalahsebuahobjekyangberisisebuah kuncidansebuahnilai.DefinisikelasdariEntrysepertidibawahini:

classEntry{ Objectkunci,value; publicEntry(Objectkunci,Objectvalue){ this.kunci=kunci; this.value=value; } publicStringtoString(){ return"{"+kunci+","+value+"}"; } }

LaluimplementasidariMapsepertidibawahini:

414

publicclassMyMap{ Vectorentries; publicMap(){ entries=newVector(); } }

UntukmenaruhentribarupadaMap,kitahanyamenambahsebuahobjekEntrypada Vector: publicvoidput(Objectkunci,Objectvalue){ entries.add(newEntry(kunci,value)); }

KemudianuntukmelihatsebuahkuncipadaMapkitaharusmenjelajahiVectordan mencarisebuahEntrydengankunciyangsesuai.

publicObjectget(Objectkunci){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(kunci.equals(entry.kunci)){ returnentry.value; } } returnnull;

415

} CarauntukmenjelajahiVectortelahkitalihatpadabagian17.10.Ketikakita membandingakankunci,kitamenggunakanmetodeequal(deepquality)daripada operator==(shallowquality).Halinimembuatdiperbolehkannyatipedatakunciuntuk menspesifikasikandefinisipersamaanyangdigunakan,Padacontohdiatas,tipedata kunciadalahString,jadimetodegetakanmenggunakanmetodeequalsyangadapada kelasString.

Karenaequalsadalahmetodeobjek.Implementasidarigettidakbekerjajikakunci berisinull,Untukmengatasikunciyangberisinull,kitaharusmenambahkankasus khususuntukmengambildanmenulissebuahmetodepadakelasyangmembandingkan kuncidanmengurusiparameternulldenganaman.Tapihalinitidakakankitabahas secaradetail.

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

} returnresult; } privatevoidupdate(Objectkunci,Objectvalue){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(kunci.equals(entry.kunci)){ entry.value=value; break; } }

MetodeupdatebukanmerupakanbagiandariMapADT,jadiiadideklarasikanprivate. IamenjelajahiVectorsampaimendapatkanobjekEntryyangtepatlalumemparbaharui atributnilainya.PerludiperhatikanbahwakitatidakmemodifikasiVector,kitahanya salahsatuobjekyangadadidalamnya.

MetodeyangbelumkitaimplementasikanadalahcontainsKeydankeySet.Metode containsKeyhampirsamadenganmetodegetkecualiiamengembalikannilaitrueatau falsesebagaigantiobjekataunull.

Latihan19.1ImplementasikanmetodekeySetdenganmembuatdanmengembalikan objekTreeSet.GunakanimplementasiTreeSetandapadabab17.7atauimplementasi yangtelahdisediakanpadapaketjava.util.TreeSet

417

ImplementasilengkapMapmenggunakanVector:
importjava.util.*; publicclassMyMap{ Vectorentries;

publicMyMap(){ entries=newVector(); }

publicObjectget(Objectkunci){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(kunci.equals(entry.kunci)){ returnentry.value; } } returnnull; }

publicObjectput(Objectkunci,Objectvalue){ Objectresult=get(kunci); if(result==null){ Entryentry=newEntry(kunci,value); entries.add(entry); }else{

418

update(kunci,value); } returnresult; }

privatevoidupdate(Objectkunci,Objectvalue){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(kunci.equals(entry.kunci)){ entry.value=value; break; } } }

publicSetkeySet(){ Iteratorit=entries.iterator(); Sets=newTreeSet(); while(it.hasNext()){ Entryentry=(Entry)it.next(); s.add(entry.kunci); } returns; }

publicbooleancontainsKey(Objectkunci){ if(get(kunci)==null)

419

returnfalse; else returntrue; }

} classEntry{ Objectkunci,value; publicEntry(Objectkunci,Objectvalue){ this.kunci=kunci; this.value=value; } publicStringtoString(){ return"{"+kunci+","+value+"}"; } }

ContohkelasWordCountmenggunakanimplementasiMapdenganVector
importjava.util.*;

publicclassWordCountVector{ MyMapMap; publicWordCountVector(){ Map=newMyMap(); }

420

publicvoidprocessLine(Strings){ StringTokenizerst=newStringTokenizer(s,",."); while(st.hasMoreTokens()){ Stringword=st.nextToken(); processWord(word.toLowerCase()); } }

publicvoidprocessWord(Stringword){ if(Map.containsKey(word)){ integeri=(integer)Map.get(word); integerj=newinteger(i.intValue()+1); Map.put(word,j); }else{ Map.put(word,newinteger(1)); } }

publicvoidprint(){ Setset=Map.keySet(); Iteratorit=set.iterator(); while(it.hasNext()){ Stringkunci=(String)it.next(); integervalue=(integer)Map.get(kunci); System.out.println("{"+kunci+","+value+"}"); } }

421

publicstaticvoidmain(String[]args){ WordCountVectorwc=newWordCountVector(); wc.processLine("youspinmerightroundbaby"+ "rightroundlikearecordbaby"+ "rightroundroundround"); wc.print();

} }

19.5KelasAbstrakList
Paketjava.utilmendefinisikansebuahkelasabstrakyangmenspesifikasikanhimpunan operasiyangsebuahkelasharusmengimplementasikanagardapatdisebutList,Initidak berartibahwasetiapkelasyangmengimplementasikanListharusmerupkanstruktur datalinkedlist.

TidakanehbahwakelasbawaanLinkedListadalahimplementasidariList.Danyang mengejutkankelasVectorjugamerupakanimplementasidarikelasList.

MetodemetodepadadefinisiListmerliputiadd,get,daniterator.Padakenyataannya, semuametodedarikelasVectoryangdigunakanuntukmengimplementasikanMap didefinisikanpadakelasabstrakList.IniberartisebagaigantikelasVector,kitadapat menggunakanimplementasikelasabstrakListapapun.PadaimplementasiMapyang telahkitabuatkitadapatmenggantiVectordenganLinkedListdanprogrammasihbisa

422

bekerjadenganbaik.

Tipeumumsepertiinidapatbergunauntukmeningkatkanperformasebuahprogram. AndadapatmembuatprogramdalambentukkelasabstraksepertiListlalumengetes programtersebutdenganbeberapaimplementasiyangberbedauntukmelihat implementasmanayangmenghasilkanperformaterbaik.

19.6ImplementasidenganHashMap
AlasanimplementasibawaanMapADTdisebutHashMapkarenaiamenggunakan sebuahimplementasiMapyangefisienmenggunakantabelhash. UntuklebihmemahamiimplementasiHashMapdanmengapaiadianggapefisien.Kita akanmemulaidenganmenganalisaperformadariimplementasiList.

Denganmelihatpadaimplementasiput,kitamelihatbahwaterdapatduakasus.Jika kuncibelumterdapatdalamMap,kitalaluhanyaakanmembuatentribarudan menambahkannyapadaMap,keduaoperasiinimerupakanoperasidenganwaktuyang konstan.

Padakasuslain,kitaharusmenjelajahiListuntukmencarisuatuentri.Yangmerupakan operasidenganwaktulinear.UntukalasanyangsamagetdancontainsKeyjuga memilikiwaktuyanglinear.

Meskipunoperasilinearseringsudahdianggapmencukupi,tetapikitadapat melakukannyalebihbaik.AdasebuahcarauntukmengimplementasikanMapADT sehinggaputdangetdilakukanpadawaktuyangkonstan.

423

KuncinyaadalahpengetahuantentangwaktupenjelajahanListyanglineardengan panjangList.JikakitadapatmeletakkanbatasataspadapanjangListmakakitadapat meletakkanbatasataspadawaktupenjelajahan,makaapapundenganbatasatasyang pastiadalahwaktukonstanyangbisadiperhitungkan.

TetapibagaimanakitadapatmembatasipanjangListtanpamembatasibanyakitempada Map?SolusinyaadalahdenganmenambahjumlahList.SebagaigantisatuListyang panjangkitaakanmenggunakanbanyakListpendek. SepanjangkitatahuListmanayangakandicari,kitadapatmeletakkanbataspada jumlahpencarian.

19.7FungsiHash
Danitulahdimanafungsihashbisadipergunakan.Kitamembutuhkancarauntuk melihatsebuahkuncidantahutanpamencari,padaListmanaiaberada.Kitaakan mengasumsikanbahwaListadadidalamarray(atauVector)jadikitabisa mereferensinyadengandenganindex.

Solusiyangbisadilakukanadalahdenganmenggunakanteknikpemetaan.Untuksetiap kemungkinankuncidipastikanterdapatsebuahindekstunggal,tetapiadakemungkinan banyakkunciyangdipetakanpadaindexyangsama.

Sebagaicontoh,Sebuaharraydengan8ListdansebuahMapyangdibuatdengankunci bertipeintegerdannilaiyangbertipeString.Untukmendapatkanindeksdigunakan metodeintValuepadakelasintegersebagaiindeks,yangmerupakantipeyangbenar,

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.

UntukStringkitabisamendapatkannilaibilangantiapkarakterdanmenambahkannya, ataukitamungkinbisamenggunakanoperasishiftedsum.Untukmenghitungnilai shiftedsum,andasecarabergiliranmenambahkannilaibarukedalamakumulatordan menggeserakumulatorkekiri.geserkekiriberartimenambahkandenganbilangan konstan.

Untukmelihatbagaimanainibekerja,ambildaftarbilangan1,2,3,4,5,6danhitung shiftedsumdengancarasebagaiberikut,pertamainisialisasiakumulatordengan0,lalu 1. Kalikanakumulatordengan10. 2. Tambahkanelemenberikutdaridaftarpadaakumulator. 3. Ulangisampaisemuabilanganpadadaftartelahdikalikansemua.

425

Sebagailatihan,tulissebuahmetodeyangmenghitungshiftedsumnilaibilangansemua karakterpadaStringmenggunakanpengali16.

Untuksetiaptipe,kitabisamembuatfungsiyangmengambilnilaidengantipetersebut danmenghasilkannilaibulatyangbersesuaian.Fungsiinidinamakanfungsihash, karenamerekaseringterlibatmembuatsebuahhashpadakomponensebuahobjek.Nilai hashdarisebuahobjekdisebuthashcode.

AdasatucaralainyangdapatdilakukanuntukmengasilkanhashcodeuntukobjekJava. SetiapobjekjavamenyediakanmetodehashCodeyangmengembalikanintegeryang bersesuaiandenganobjektersebut.Untuktipebawaanjava,metodehashCode diimplementasikansehinggajikaduaobjekyangmemilikidatayangsama,merekaakan memilikihashcodeyangsama.Dokumentasidarimetodeinimenjelaskanapaitu fungsihash.Andalebihbaikmengeceknyauntukmengetahuilebihlanjut.

Untuktipeyangdidefinisikanpengguna,halinitergantungpadapengimplementasi untukmenyediakanfungsihashyangsesuai.Fungsihashdefault,yangdisediakanpada kelasObject,Seringmenggunakanlokasiobjekuntukmengasilkanhashcode,jadi notasinyauntuksuatukesamaanadalahshallowequality.Seringketikakitamencari sebuahkuncipadaMapkesamaanyangmenggunakanshallowequalitybukan merupakanyangkitainginkan.

Terlepasdaribagaimanacaramenghasilkanhashcode,langkahterakhiradalah menggunakanmodulusdanfungsinilaiabsolutuntukmemetakanhashcodepada

426

rentangindeksyanglegal.

19.8MengubahUkuranHashMap.
Sebuahhashtableberisisebuaharray(atauVector)yangelemennyamerupakansebuah List.DimanasetiapListberisijumlahentriyangkecil.Untukmenambahentribaru padaMap,kitamenghitunghashcodepadakunciyangbarudanmenambahentri tersebutpadaListyangsesuai. Untukmencarisebuahkunci,kitamenghitunghashlagidanmencarinyapadaListyang sesuai.JikapanjangListterbatasmakawaktupencarianjugaterbatas.

JadibagaimanacaramembuatListtetappendek?Salahsatutujuanadalahbagaimana sebisamungkinsemuaListtersebuttetapseimbang.JaditidakakanadaListyangsangat panjangdanpadasaatyangsamaListlainkosong.Halinibukanhalyangmudahuntuk dilakukansecarasempurna,iatergantungpadaseberapabaikkitamemilihfungsihash.

Bahkandengankeseimbanganyangsempurna,rataratapanjangListberkembangsecara lineardenganjumlahentri.Dankitaharusmeletakkantitikhentipadasaatitu.

SolusinyaadalahdenganmengikutirataratajumlahentriuntuksetiapList,yangdisebut loadfactor.Jikaloadfactorterlalutinggikitaharusmengubahukuranhashtable.

Untukmengubahukuran,kitamembuathashtablebaru,biasanyaduakalilebihbesar dariyangasli,ambilsemuaentriyangadapadahashtableyanglama.Mengenainya denganfungsihash.Danmeletakkannyakembalipadahashtableyangbaru.Biasanya kitabisamenggunakafungsihashyangsama.Kitahanyamenggunakannilaiyang

427

berbedauntukoperatormodulus.

19.9Kinerjadaripengubahanukuran

Berapalamawaktuyangdibutuhkanuntukmengubahukuranhashtable?Yangjelasia sebandingdenganbanyakentri.Ituberartisebagianbesarwaktuputmembutuhkan waktuyangkonstan,tetapisesekaliketikakitamelakukanpengubahanukuraniaakan membutuhkanwaktuyanglinear.

Padaawalnyahalinimemangburuk.Bukankahinimenyalahiklaimsayabahwakita melakukanputdenganwaktuyangkonstan?Terusterangya.Tetapidengansedikit pengaitan,kitabisamemperbaikinya.

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.

Dengandimasukkanpadapersamaanmakakitadapatkan t(n)=c+1/nkn=c+k (19.2) Dengankatalain,t(n)adalahwaktuyangkonstan.

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

latihan19.3 Bayangkanandamemilikisebuahhashtableyangberisi100List.Jikaandaingin mengambilsebuahnilaiyangbersesuaiandengankuncitertentu,dankodehashdari kuncitersebutadalah654321,padaindeksListkeberapakahkuncitersebutakanberada (jikaberadadalammap)?

Latihan19.4 Jikaterdapat100Listdanterdapat89entripadamapdanListterpanjangberisi3entri, danpanjanglisttengah(median)adalah1dan19%listadalahkosong,berapakahload factornya?

Latihan19.5 Bayangkanterdapatbanyakorangpadasebuahpesta.Andainginmengetahuiapakah adadiantaramerekayangmemilikihariulangtahunyangsama.Pertamaanda mendesainsebuahobjekJavayangmewakilihariulangtahundenganduavariabel instance:bulanyangmerupakanbilanganbulatantara1dan12,danhariyang merupakanbilanganbulatantara1dan31. 430

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.

Latihan19.6 SebuahMapdisebutinvertiblejikasetiapkuncidansetiapnilaihanyamunculsekali. PadaHashMapselalubenarbahwasetiapkuncihanyamunculsekali,tetapiada memnungkinkannilaiyangsamamunculbeberapakali.Itulahmengapa,beberapa HashMapinvertible,danbeberapatidak. TulissebuahmetodeyangbernamaisInvertibledenganparameterHashMapdan mengembalikantruejikamapinvertibledanfalsejikatidak.

431

Latihan19.7 Tujuanlatihaniniadalahuntukmencari20katakatayangpalingseringdipakaipada bukuini(bukuiniyangmasihdalambahasainggris).Tulislahkodeyangmenggunakan HashMapuntukmenghitungfrekuensikemunculankata.Downloadteksbukupada alamathttp://kleq.web.ugm.ac.id/images/thinkapjava.txt.Pikirkanbagaimana seharusnyaprogramandamenanganitandabacadanhalhallainyangmunculpada berkas.

Tulisprogramuntukmenjawabpertanyaanpertanyaandibawahini: a. Berapabanyakkatayangadapadabukuini? b. Berapabanyakkatayangberbedamunculpadabukuini? c. Berapakalikataencapsulationmuncul? d. Apasaja20katakatayangpalingseringmuncul?Petunjuk:Adastrukturdata lainyangmungkinbisamembantuuntukbagianlatihanini.

Latihan19.8 TulissebuahmetodeuntukLinkedListyangmengecekapakahlistmengandungloop. AndatidakbolehmengasumsikanbahwapanjangListtelahbenar.

Latihan19.9 TulisimplementasiMapADTyangmenggunakahashtable(sepertiyangdidefinisikan padabagian19.2).Ujilahdenganprogramprogramyangtelahandabuatsebelumnya. a. MulailahdenganimplementasiVectorpadabukuini b. UbahimplementasidenganmenggunakanarraydariLinkedListatauVector yangberisiLinkedList. Latihan19.10 432

BuatimplementasiSetmenggunakanHashMap

Latihan19.11 Paketjava.utilmenyediakanduaimplementasiMap,yaituHashMapdanTreeMap, HashMapdibangundenganmeniruhashtablesepertiyangdijelaskanpadababini. TreeMapdibuatberdasarkanredblacktree,yangmiripdenganpohonpencarianpada latihan17.6. Meskipunkeduaimplementasiinimeyediakanantarmukayangsama,kita mengharapkannyamencapaikinerjayangberbeda.Sejalandenganbanyakentrin bertambah,kitaberharapadddancontainsmenggunakanwaktukonstanuntuk implementasihashtable.Danwaktuyanglogaritmikuntukimplementasidengan pohon.

Lakukanpercobaanuntukmengkonfirmasi(ataumembantah)prediksiini,Buatsebuah programyangmenambahnentripadaHashMapatauTreeMap,lalupanggilcontains untuksetiapkuncipadaentritersebut.Catatwaktupengeksekusianprogramterhadap nilaindanbuatgrafiknya.Apakahkinerjasesuaidenganperkiraankita?

433

BAB20 KodeHuffman 20.1Variabellengthcodes


Jikaandafamiliardengankodemorse,andamengetahuibahwamorseadalahsistem untukmengkodekanhurufpadaalfabetmenjadititikdangaris.Misalnyasinyalterkenal ......mewakilihurufSOSyangtermasukkodepanggilaninternasionaluntukmeminta pertolongan. Tabelberikutmemperlihatkankodetersebut:

Perhatikanbahwabeberapakodelebihpanjangdibandingkandenganyanglain.Pada perancangan,hurufyangpalingseringdigunakanmemilikikodeterpendek.Karena terbatasnyakodependeksehinggahurufhurufdansimbolyanglainmemilikikodeyang lebihpanjang.Suatupesanakanmemilikilebihbanyakkodependekdibandingkankode yangpanjang,sehinggameminimalisasirataratatransmisiperhuruf.

434

Kodesepertiinidisebutvariablelengthcodes.Padababinikitaakanmelihatalgoritma untukmembangkitkanvariablelengthcodesyangdisebutkodeHuffman.Huffman merupakanalgoritmayangmenarik,tetapijugamerupakanlatihanyangbergunakarena implementasinyamenggunakanbanyakstrukturdatayangtelahkitapelajari. Dibawahinigarisbesaruntukbeberapabagianberikutnya:

Pertama,kitaakanmenggunakansebuahcontohteksdalambahasinggrisuntuk menghasilkantabelfrekuensi.Tabelfrekuensimiripsepertihistogram,ia menghitungberapakalisetiaphurufmunculpadatekscontoh.

Intidarikodehuffmanadalahpohonhuffman.Kitaakanmenggunakantabel frekuensiuntukmembangunpohonhuffman,lalumenggunakanpohonuntuk mengkodekandanmemecahkodedarirangkaianyangada.

Langkahterakhir,kitaakanmenjelajahiphonhuffmandanmemanguntabel kode,yangberisirangkaiantitikdangarisuntuksetiappohon.

20.2Tabelfrekuensi
Karenatujuannyaadalahmemberikankodependekpadakatayangumum,kitaharus tahuberapakalisetiaphurufmuncul.PadaceritapendekEdgarAllenPoeTheGold Bug,salahsatukaraktermenggunakanfrekuensihurufuntukmemecahkanchiper.Dia menjelaskan

Sekarangdalambahasainggris,hurufyangpalingseringmunculadalahe, setelahituaoidhnrstuycfglmwbkpqxz.

JadimisipertamakitaadalahmelihatapakahPoebenar.

435

Latihan20.12 TulissebuahkelasyangbernamaFreqTabyangmenghitungberapakalisetiaphuruf munculpadatekscontoh.Downloadcontohteksceritapendekfavoritanda,dananalisa frekuensimasingmasinghuruf.

SayamenemukanbahwalebihtepatmembuatkelasFreqTabditurunkandariHashMap. Lalumenulismetodeincrementyangmengambilhurufsebagaiparameterdan menambahataumemperbaharuientridalamHashMapuntuksetiaphuruf.

AndadapatmenggunakankeySetuntukmengambilentripadaHashMap,danmencetak daftarhurufdanfrekuensinya.Sayangnya,merekatidakakantampilsecaraberurutan. Latihanberikutmenyelesaikanmasalahini.

Latihan20.13 TulissebuahkelasyangbernamaPairyangmewakilipasanganhurufdanfrekuensi. Objekpairharusberisisebuahhurufdanfrekuensisebagaivariabelinstance.Pairharus mengimplementasikanComparablesehinggaobjekPairdenganfrekuensilebih tinggilahyangmenang.

SekarangurutkanpasanganhurufdanfrekuensidariHashMapdenganmenjelajahi himpunankunci,buatobjekPair,tambahkanPairpadaPriorityQueue,ambilPairdari PriorityQueuedancetakdenganurutanmundurberdasarkanfrekuensi.

436

20.3PohonHuffman
Langkahberikutnyaadalahmembangunpohonhuffman.Setiapsimpulpadapohon berisisebuahhurufdanfrekuensinya,sertapenunjukkesimpulkiridankanan.Untuk membangunpohonHuffman,kitamulaidenganmembuathimpunanpohontunggal, satudarisetiapentripadatabelfrekuensi.Lalukitamembangunpohondaribawahke atas,dimulaidarihurufdenganfrekuensiterendahdansecaraberulangmenggabungkan subphonsampaimendapatkanpohontunggalyangberisisemuahuruf.

DibawahinialgoritmauntukmembangunpohonHuffmansecaralebihdetil. 1. Untuksetiapentripadatabelfrekuensi,buatpohonHuffmantunggaldan tambahkanpadaPriorityQueue.Sehinggaketikakitamengambilpohondari PriorityQueue,kitamendapatkanyangmemilikifrekuensiterendah. 2. AmbilduapohondariPriorityQueuedangabungkandenganmembuatsebuah simpulorangtuayangmenunjukpadapohonyangdiambiltadi.Frekuensi simpulorangtuaadalahjumlahandarifrekuensianakanaknya. 3. JikaPriorityQueuekosong,makaalgoritmaselesai,jikatidakletakkanpohon barupadaPriorityQueuekembalikelangkah2.

Sebagaicontohkitaakanmenggunakanteksdibawahuntukmembentukpohon Huffman.

EasternTennesseeanteatersensnareandeatredants,detestant antennae(atarttaste)anddreadAntareananteatereaters.Rare Andeandeereattenderseareeds,asterseedsandratsears.Dessert? Ratsasses. 437

Teksdiatasmenghasilkantebelfrekuensi: e a t s n r d 40 32 24 22 20 19 13

Jadisetelahlangkah1,PriorityQueueakanterlihatseperti:

Padalangkah2,kitamengambilduapohondenganfrekuensiterendah(rdand)dan menggabungkannyadenganmembuatsimpulorangtuadenganfrekuensi32.Nilai hurufuntuksimpulinternalkurangrelevan,sehinggadihapusdarigambar.Ketikakita meletakkanpohonbarukembalikePriorityQueue.Hasilnnyaakansepertidibawah:

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

.. .. . .... ...

Perhatikanbahwakitatelahmencapaitujuan:hurufdenganfrekuensiterbanyak memilikikodepalingpendek. Latihan20.14 Denganperhitunganmanual,gambarkanpohonHuffmanuntuktabelfrekuensiberikut: e s r t n i d o 93 71 57 53 49 44 43 37

20.4Metodesuper
SalahsatucarauntukmengimplementasikanpohonHuffmanadalahdengan menurunkannyadarikelasPairdarilatihan20.13 publicclassHuffTreeextendsPairimplementsComparable{ HuffTreeleft,right; publicHuffTree(intfreq,Stringletter, HuffTreeleft,HuffTreeright){ 440

this.freq=freq; this.letter=letter; this.left=left; this.right=right; } } HuffTreemengimplementasikanComparablesehinggakitabisameletakkanpohon HuffmankedalamPriorityQueue.UntukmengimplementasikanComparable,kita harusmenyediakanmetodecompareTo.Kitabisamenuliskannyadariawal,tetapiakan lebihmudahjikamenggunakanversicompareTodarikelasPair.

Sayangnya,metodetersebuttidakmelakukanapatepatnyayangkitainginkan.Untuk Pairkitamemberikanprioritasuntukfrekuensiyanglebihtinggi.Sedangpadapohon Huffman,kitamenginginkanmemberikanprioritaspadafrekuensiyanglebihrendah. Tentusaja,kitabisamenuliskanversibarudaricompareTotetapiitutentunyaakan menutupi(override)versipadakelasdiatasnya(kelasorangtua),padahalkitaingin bisamemanggilversimetodeyangadapadakelasorangtua.

Katakuncisupermengijinkankitauntukmemanggilmetodeyangtelahditutup.Ia disebutsuperkarenakadangkadangkelasorangtuajugadisebutsuperclasses. BerikutcontohdariimplementasiHuffTree: publicintcompareTo(Objectobj){ returnsuper.compareTo(obj); }

441

KetikacompareTodipanggilpadaHuffTree,iaakanmemanggilversicompareTopada kelasorangtua,danmenegatifkanhasilnya.Sehinggaurutanprioritasmenjaditerbalik.

Ketikakelasanak(jugadisebutsubclass)menutupiconstructor,iabisamemanggil konstruktorkelasorangtuadenganmenggunakansuper: publicHuffTree(intfreq,Stringletter, HuffTreeleft,HuffTreeright){ super(freq,letter); this.left=left; this.right=right; } Padacontohini,konstruktororangtuamenginisialisasifreqdanletter,danlalu konstruktoranakmenginisialisasileftdanright.

Meskipunfituriniberguna,iajugamemillikikecenderunganuntuksalah.Adabeberapa keterbatasansepertimisalkonstruktororangtuaharusdipanggilpertama,sebelum variabelinstancelaindiinisialisasi,danadabeberapahalyangtidakinginandaketahui. Secaraumum,mekanismeinisepertiperlengkapanp3k.Ketikaandamengalami masalahiabisamembantuanda.Tetapiandatahuapayanglebihbaik?Janganmasuk kedalammasalah.Padamasalahini,lebihmudahuntukmenginisialisasikesemua empatvariabelinstancepadakonstruktoranak.

Latihan20.15 TulisdefinisikelasHuffTreedaribagianinidansebuahkelasdenganmetodebuildyang mengambilsebuahFreqTabdanmengembalikansebuahHuffTree.Gunakanalgoritma

442

padabagian20.3.

20.5PemecahanKode
Ketikakitamenerimapesanyangdikodekan,kitamenggunakanpohonHuffmanuntuk memecahkodenya.Dibawahinialgoritmauntukmelakukanhaltersebut: 1. MulaidariakarpohonHuffman 2. Jikasimbolberikutnyaadalah.,makaberlanjutkeanaksebelahkiri,jikatidak makaberlanjutkeanaksebelahkanan. 3. Jikaandaberadapadasimpuldaun.Ambilhurufnyadantambahkanpadahasil. Lalukembalikeakar. 4. Kelangkah2.

Perhatikankode....,sebagaicontoh.Mulaidaripuncakpohon,kitamenujukirikiri kanandanmendapatkanhuruft.kemudiankitamulaidariakarlagi,kanankiridan mendapatkanhurufe,kembalikepuncak,lalukanankiridankitamendapatkanhurufa. jikakodenyadibentukdenganbaik,kitaseharusnyaadapadasimpuldaunketikakode berakhir.Padakasusinipesannnyaadalahtea.

Latihan20.16 GunakancontohpohonHuffmanuntukmemecahkankodeberikut: a...... b............. c.......... d......

Perhatikanketikaandamulaimemecahkankode,andatidakdapatmengetahuiberapa 443

banyakhurufpadakodeatauberadadimanabatasbatashurufnya.

Latihan20.17 TulisdefinisikelasHuffman.KonstuktormemilikiparameterStringyangmengandung contohteks.KelasharusbisamembuattabelfrekuensidanpohonHuffman. Buatmetodeyangbernamadecode.Metodeinimenggunakanparameterdalambentuk titikdangarisdanmenggunakanpohonHuffmanuntukmemecahkankodedan mengembalikanhasilnya.

Catatan:Walaupunandamenggunakancontohkalimatpadabagian20.2,andatidak akanmendapatkanpohonHuffmanyangsamasepertipadabagian20.3,jadi kemungkinanandatidakakanbisamenggunakanprogramandauntukmemecahkan kodepadacontohlatihansebelumnya.

20.6Pengkodean
Biasanya,pengkodeanlebihsulitdibandingkandenganpemecahankode,karenauntuk suatuhurufkitaharusmencarisimpuldaunpadapohonyangberisihuruftersebutdan dilanjutkandenganmenggambarkanlintasandariakarsampaisimpultersebut.

Prosesiniakanlebihefisienjikakitamenjelajahipohonsekali,memprosessemuakode, danmembangunMapdarihurufkekode(hurufsebagaikuncidankodesebagainilai).

Darisekarangkitatelahmelihatbanyakpohonpenjelajahan,tetapiyangsatuinitidak biasakarenasaatkitamenjelajahipohin,kitajugainginmenyimpanlintasan/jalan dimanakitaberada.Awalnyainimemangkelihatansulit,tetapiadacarayanglebih alamiuntukmelakukanperhitungansecararekursif.Kuncinyaadalalahjikalintasandari 444

akarkesuatusimpuldisimbolkandenganrangkaiantitikdangarisyangdisebut lintasan,makalintasankeanakkiripadasimpuladalahlintasan+''danlintasanke anaksebelahkananadalahlintasan+'.'.

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.

UntukmengatasihaldiatasmakasaatpembentukanCollection,telahdiberitahulebih dahulutipeapayangakanadadidalamCollectioninilahyangdisebutgenerik.Generik dilakukandenganmenambahkantipedata/tipeobjeksaatpendeklarasianCollection. Contohdeklarasilama:


Listl=newArrayList(); Sets=newHashSet();

Contohdeklarasidengangenerik:
List<Integer>l=newArrayList<Integer>(); Set<Double>s=newHashSet<Double>();

PenggunaanGenerikmengakibatkanduahal: 1.KompilerakanmengecekapakahelemenyangditambahkankedalamCollection validatautidaksehinggasaatandamenambahkanelemenyangbertipedataberbeda denganyangbisaditerimaCollectionmakaakanterjadiCompileError.

446

importjava.util.*;

classTest{ publicstaticvoidmain(String[]args){ List<Integer>l=newArrayList<Integer>(); } } l.add(newInteger(1));

PadakodediatasCollectionyangberupaListhanyaakanmenerimadatayangbertipe Integer.KetikaandamencobamenambahkantipedatayanglainkedalamListtersebut makalisttersebutakanerror.

importjava.util.*;

classTest{ publicstaticvoidmain(String[]args){ List<Integer>l=newArrayList<Integer>(); l.add(newDouble(1)); } }

SebagaicontohsayamencobamemasukkandatabertipeDouble.Jikaanda menggunakanJava 1.5keatas,kodeakanmengalamierrorsaatkompilasi,tetapi tidakjikaandamenggunakanversisebelumnya.

2.DalampengambilanobjekdariCollectionandatidakperlulagimelakukan pengcastingankarenatipedatayangadapadaCollectiontelahdidefinisikanlebih dahulu.

447

importjava.util.*; classTest{ publicstaticvoidmain(String[]args){ List<Integer>l=newArrayList<Integer>(); l.add(newInteger(1)); Integeri=l.get(0); } }

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

DalampenggunaaniteratorseperticontohdiatasuntukmenjelajahiCollectionsatu persatudiperlukanminimal2bariskode,yaitumengambilobjekiteratordan mengiterasinyamenggunakanwhile. Denganforeachhaldiatasbisadisederhanakan


importjava.util.*;

classTest{ publicstaticvoidmain(String[]args){ List<Integer>l=newArrayList<Integer>(); l.add(1); l.add(2); for(Integeri:l){ System.out.println(i); } } }

JikasebelumnyauntukmenjelajahiCollectiondibutuhkanminimalduabariskode, makadenganforeachkitahanyamembutuhkansatubariskode.Foreachjuga sepenuhnyamenggunakankemampuangeneriksehinggakitatidakperlupengcastingan lebihdahulu.

Secaraumumsyntaxforeachadalah:
for(<tipedatadalamCollectionatayarray><namavariabel>:<Collectionatauarrayyangakan dijelajahi>) <statemen>

Dalampenggunaannyadalamarray,foreachtidakterlalubanyakbergunakarena denganmenggunakanperulanganforbiasapenjelajahanarraybisadilakukandengan 449

maksimal.Salahsatukelebihanforeachdibandingkandenganfordalampenjelajahan arrayadalahsyntaxyangsederhanadantidakperlunyamenggunakanindekssaat mengakseselemendalamarray.

importjava.util.*; classTest{ publicstaticvoidmain(String[]args){ int[]arr={1,4,5}; for(inti:arr) System.out.println(i); } }

Tetapidalammenjelajahiarrayforeachmemilikiketerbatasan,bahwadidalamforeach kitatidakbisamelakukanpemanipulasianterhadapisiarray.Karenaforeachtidak mereferensilangsungpadaisiarraytersebut.


importjava.util.*; classTest{ publicstaticvoidmain(String[]args){ int[]arr={1,4,5}; for(inti:arr) i=i+1; for(inti:arr) System.out.println(i); } }

Kodediatassamasekalitidakakanmengubahisiarrayarray.Sehinggasaatanda mencetaknyayangtampiltetaparrayyangasli.

450

DaftarKata
Collection:TipeumumStrukturdataJava,strukturdataList,Set,Map,danlainlain diturunkan darikelasini.Biasanyadigunakanuntukmengacupadakeseluruhan

strukturdatapadaJava. RuntimeException:EksepsiyangdilemparJavaketikaterjadikesalahansaatprogram Java dijalankan

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); } }

Latihan2.2 classTime{ publicstaticvoidmain(String[]args){

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

Latihan3.2 No,Iwug. Youwuggawug. Iwug.

Latihan3.3 classLatihan{ publicstaticvoidzool(inta,Stringb,Stringc){ }

publicstaticvoidmain(String[]args){ zool(11,"chicken","gajahmada"); } }

454

Latihan3.4 classDate{

publicstaticvoidprintAmerican(Stringhari,inttanggal,Stringbulan,int tahun){ System.out.println(hari+","+bulan+""+tanggal+","+tahun); }

publicstaticvoidprintEuropean(Stringhari,inttanggal,Stringbulan,int tahun){ System.out.println(hari+""+tanggal+""+bulan+","+tahun); }

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

} }

Latihan3.5 classMultadd{ publicstaticvoidmultadd(doublea,doubleb,doublec){ System.out.println(a*b+c); }

publicstaticvoidmain(String[]args){ multadd(1.0,2.0,3.0); //phi=180' //Math.log10adapadajavaversi5(1.5) multadd(Math.cos(180/4),0.5,Math.sin(180/4)); multadd(1,Math.log10(10),Math.log10(20)); yikes(3); }

publicstaticvoidyikes(doublex){ multadd(x,Math.exp(x),+(Math.sqrt(1Math.exp(x)))); } }

Bab4
Latihan4.1 456

main nLines nLines nLines nLines


n 4

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

Iterasike 1 2 3 4 5 6 7 8 9 b. Looptakberhingga 10 5 6 4 3 2 1 2 1 . Latihan6.2. a.publicstaticintfooMethod(Strings){ intlen=s.length();

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);

if(c=='('){ count=count+1; }elseif(c==')'){ count=count1; } i=i+1; }

returncount; } b.Metodeyangjikaterdapatkurungbukamenambah1isivariabelcounterdanjika terdapatkurungtutupakanmengurangi1nilaicounter.Metodeinibergunauntuk menentukanapakahsuatuekspresiyangmenggunakantandakurungtelahvalid(masing masingmemilikikurungpasangan)atautidak. c.Pasangankarakteryangakandiceksebaiknyadapatdiubahubahsesuaikeperluan classTest{ publicstaticvoidmain(String[]args){ System.out.println(fooMethod("((3+7)*2)",'(',')'));

459

publicstaticintfooMethod(Strings,charkar1,charkar2){ intlen=s.length();

inti=0; intcount=0;

while(i<len){ charc=s.charAt(i);

if(c==kar1){ count=count+1; }elseif(c==kar2){ count=count1; } i=i+1; }

returncount; } } Latihan6.3 publicstaticdoublesquareRoot(doublenumber){ doublex0=number/2;

460

doublex2=100; doublex1=90; while(Math.abs(x2x1)>=0.0001){ x1=(x0+number/x0)/2; x2=(x1+number/x1)/2; x0=x2; } returnx2; }

Latihan6.4 publicstaticdoublepower(doublex,intn){ doubleresult=1; for(inti=1;i<=n;i++) result*=x; returnresult; }

Latihan6.5 publicstaticintfaktorial(intx){ intresult=1; while(x!=1){ result*=x; x=1; }

461

returnresult; } Latihan6.6 a) publicclassLatihan66{

publicstaticintfaktorial(intx){ intresult=1; while(x!=1){ result*=x; x=1; } returnresult; }

publicstaticdoublemyexp(doublex,intn){ doubleresult=1; for(inti=1;i<=n;i++){ result+=power(x,i)/faktorial(i); } returnresult; }

publicstaticdoublepower(doublex,intn){ doubleresult=1; 462

for(inti=1;i<=n;i++) result*=x; returnresult; } } b. publicclassLatihan66{

publicstaticintfaktorial(intx){ intresult=1; while(x!=1){ result*=x; x=1; } returnresult; }

publicstaticdoublemyexp(doublex,intn){ doubleresult=1; doublenumerator=1; doubledenominator=1; for(inti=1;i<=n;i++){ numerator*=x; denominator*=i; result+=numerator/denominator; 463

} returnresult; }

publicstaticdoublepower(doublex,intn){ doubleresult=1; for(inti=1;i<=n;i++) result*=x; returnresult; } }

c) publicstaticvoidcheck(doublex){ System.out.println(x+"\t"+Math.exp(x)+"\t"+myexp(x,100)); }

Latihan6.7 publicstaticdoublegauss(doublex,intn){ doubleresult=1; doublexvalue=1; doubledenominator=1; intsign=1; for(inti=1;i<=n;i++){ sign=sign*(1); 464

xvalue*=x; denominator*=i; result+=sign*(i+1)*xvalue/denominator; } returnresult; }

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.2 Metodebingmencetaksetiapkarakterpadakalimatbesertaindeksnyamulaidarihuruf palingakhir.

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; }

Latihan7.7 publicstaticbooleanisDupledrome(Stringstr){ char[]charArr=str.toLowerCase().toCharArray(); for(inti=0;i<charArr.length;i+=2){ if(i+1>=charArr.length||charArr[i]!=charArr[i+1]) returnfalse;

467

} returntrue; }

Latihan7.8 publicclassName{ publicstaticbooleanhasComma(Stringstr){ char[]charArr=str.toCharArray(); for(inti=0;i<charArr.length;i++){ if(charArr[i]==',') returntrue; } returnfalse; }

publicstaticStringconvertName(Stringname){ if(hasComma(name)) returnname; elseif(name.split("").length==1) returnname; else{ Stringbackname=""; inti=0; for(i=name.length()1;i>=0;i){

468

if(name.charAt(i)=='') break; else backname=name.charAt(i)+backname; } returnbackname+","+name.substring(0,i); } }

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

else return0; } } Latihan7.9 publicstaticcharadd(charc,intaddition){

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;

} elseif(Character.isUpperCase(c)){ if(addition>26||addition<26) addition%=26; intascii=(char)c; ascii+=addition; if(ascii>90) 470

ascii=64+(ascii90); elseif(ascii<65) ascii=90+(64ascii); return(char)ascii;

} returnc; }

Bab8
latihan8.1 b) 5 1 2

Latihan8.2

Latihan8.3 (5,8) (5,8) 471

p1danp2bukanmerupakanalias, karenamasingmasingobjekdibuatsaatpemanggilang"findCenter" importjava.math.BigInteger;

Latihan8.4

classBig{ publicstaticintfactorial(intn){ intresult=1; for(inti=n;i>=1;i){ result*=i; } returnresult;

publicstaticBigIntegerbigfactorial(intn){ BigIntegerresult=BigInteger.valueOf(1); for(inti=n;i>=1;i){ result=result.multiply(BigInteger.valueOf(i)); } returnresult;

472

publicstaticvoidmain(String[]args){ for(inti=1;i<=20;i++){ System.out.println("factorial"+i+"="+Big.bigfactorial(i)); } } }

Latihan8.5 publicstaticBigIntegerpow(intx,intn){ if(n==0) returnBigInteger.valueOf(1); BigIntegert=pow(x,n/2);

if(n%2==0) returnt.multiply(t); else returnt.multiply(t).multiply(BigInteger.valueOf(x)); }

Bab9

Latihan9.1 publicclassTile{ 473

intvalue; charletter;

publicTile(charc,intv){ letter=c; value=v; }

publicstaticvoidprint(Tilet){ System.out.println("letter"+t.letter+"hasvalue"+t.value); }

publicstaticvoidtestTile(){ Tilet=newTile('z',10); Tile.print(t); } }

latihan9.2 publicclassDate{ intdate; intmonth; intyear;

publicDate(){}

474

publicDate(intd,intm,inty){ date=d; month=m; year=y; }

publicstaticvoidmain(String[]args){ Dated=newDate(11,7,1986); Dated1=newDate(); d1.date=11; d1.month=7; d1.year=1986; } }

Latihan9.3 publicclassRational{ intnumerator; intdenominator;

publicRational(){ numerator=0; denominator=0; }

publicRational(inta,intb){ 475

numerator=a; denominator=b; }

publicstaticvoidprintRational(Rationalr){ System.out.println(r.numerator+"/"+r.denominator); }

publicvoidnegate(){ numerator=numerator; }

publicvoidinvert(){ inttemp=numerator; numerator=denominator; denominator=temp; }

publicstaticdoubletoDouble(Rationalr){ return(double)r.numerator/r.denominator; }

publicstaticintgcd(inta,intb){ if(b>a){ inttemp=a; a=b; 476

b=temp; } while(b>1){ inttemp=b; b=a%b; a=temp; }

if(b==1) return1; else returna;

publicstaticRationalreduce(Rationalr){ intgcd=gcd(r.numerator,r.denominator); System.out.println("gcd="+gcd); Rationalnumber=newRational(); number.numerator=r.numerator/gcd; number.denominator=r.denominator/gcd; returnnumber; }

publicstaticRationaladd(Rationalr1,Rationalr2){ 477

returnnew Rational(r1.numerator*r2.denominator+r2.numerator*r1.denominator,r2.denominator*r 1.denominator); }

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

classRandomClass{ publicstaticdoublerandomDouble(doublelow,doublehigh){ 478

returnlow+(Math.random()*(high1)); }

publicstaticintrandomInt(intlow,inthigh){ returnlow+(int)(Math.random()*(high1)); }

publicstaticvoidmain(String[]args){ System.out.println(randomDouble(0.6,7.8)); System.out.println(randomInt(7,8)); } }

Latihan10.3 publicstaticint[]scoreHist(int[]scores){ int[]counts=newint[100]; for(inti=0;i<scores.length;i++){ intindex=scores[i]; counts[index]++; } returncounts; }

latihan10.4 publicstaticbooleanareFactors(intnumber,int[]factors){ for(inti=0;i<factors.length;i++){ 479

if(number%factors[i]==0) continue; else returnfalse; } returntrue; }

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; }

Latihan10.8 a.30 b.bob==>0>2 1>4 2>6 3>8 4>10 c.menjumlahkansemuaelemenarraydanmengembalikannilainya

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); }

publicstaticintfindInRange(int[]arr,intbil,intlow,inthigh){ if(low==high){ if(arr[low]==bil) returnlow; else return1; } intmid=(low+high)/2; 482

intresult=findInRange(arr,bil,low,mid); if(result==1){ intresult1=findInRange(arr,bil,mid+1,high); returnresult1; }else returnresult;

publicstaticvoidmain(String[]args){ int[]arr={1,4,5,7}; System.out.println(findInRange(arr,71,0,3)); } }

Latihan10.10 classSorter{ publicstaticintindexOfMaxInRange(int[]arr,intlow,inthigh){ intmax=low; for(inti=low+1;i<=high;i++) if(arr[i]>arr[max]) max=i; returnmax; } 483

publicstaticvoidswap(int[]arr,intindex,intindex1){ intswap=arr[index]; arr[index]=arr[index1]; arr[index1]=swap; }

publicstaticint[]sortArrays(int[]arr){ for(inti=0;i<arr.length1;i++){ intindex=indexOfMaxInRange(arr,i,arr.length1); swap(arr,i,index); } returnarr; }

publicstaticvoidmain(String[]args){ int[]arr={4,5,6,0,23,12}; arr=sortArrays(arr); for(inti=0;i<arr.length;i++) System.out.println(arr[i]); } }

latihan10.11 //blanktilesdiwakiliolehspasi('') classLetterHist{ 484

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){ intcount[]=letterHist("afathkFFUhskldh"); for(inti=0;i<count.length;i++) System.out.println(count[i]); } }

latihan10.12 classDoubloon{ publicstaticbooleanisDoubloon(Stringword){ intcount[]=LetterHist.letterHist(word); for(inti=0;i<count.length;i++) 485

if(count[i]==2||count[i]==0) continue; else returnfalse; returntrue; }

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

publicstaticbooleantestWordModif(Stringtiles,Stringwords){ int[]tilesCount=LetterHist.letterHist(tiles); int[]wordCount=LetterHist.letterHist(words); intfalseCount=0; for(inti=0;i<wordCount.length;i++){ if(wordCount[i]<=tilesCount[i]) continue; else falseCount++;

} if(falseCount<=tilesCount[26]) returntrue; else returnfalse; }

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; }

publicstaticinthandScore(Card[]card){ inttotal=0; for(inti=0;i<card.length;i++){ intscore=card[i].getRank(); if(score>10) score=10; total+=score; } returntotal; }

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; }

publicstaticintStringToRank(Stringstr){ intresult=99; try{ result=Integer.parseInt(str); if(result>=2&&result<=10) returnresult; else return99;

}catch(NumberFormatExceptione){ str=str.toLowerCase(); if(str.equals("ace")) 489

return1; if(str.equals("jack")) return11; if(str.equals("queen")) return12; if(str.equals("king")) return13; else return99;

} }

publicstaticCardparseCard(Stringstr){ String[]token=str.split("of"); intrank=StringToRank(token[0]); intsuit=StringToSuit(token[1]); System.out.println(suit+""+rank); if(rank==99||suit==99) returnnull; else returnnewCard(suit,rank); }

publicstaticint[]suitHist(Card[]card){ int[]hist=newint[4]; 490

for(inti=0;i<card.length;i++) hist[card[i].getSuit()]++; returnhist; }

publicstaticbooleanisFlush(Card[]card){ int[]hist=suitHist(card); for(inti=0;i<hist.length;i++){ if(hist[i]>=5) returntrue; else continue; } returnfalse; }

publicstaticvoidmain(String[]args){ parseCard("1ofDiamonds"); } }

classCard{ intsuit; intrank;

publicCard(){ 491

suit=0; rank=0; }

publicCard(ints,intr){ suit=s; rank=r; }

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); }

publicstaticbooleanisThreeKind(Deckd){ Card[]cards=d.cards; int[]counter=newint[13]; for(inti=0;i<cards.length;i++){ counter[cards[i].getRank()]++; }

for(inti=0;i<counter.length;i++){ if(counter[i]==3) returntrue; else continue; }

returnfalse; } publicstaticbooleanisFourKind(Deckd){ Card[]cards=d.cards; 494

int[]counter=newint[13]; for(inti=0;i<cards.length;i++){ counter[cards[i].getRank()]++; }

for(inti=0;i<counter.length;i++){ if(counter[i]==4) returntrue; else continue; }

returnfalse; }

publicstaticbooleanisPair(Deckd){ Card[]cards=d.cards; int[]counter=newint[13]; for(inti=0;i<cards.length;i++){ counter[cards[i].getRank()]++; }

for(inti=0;i<counter.length;i++){ if(counter[i]==2) returntrue; else 495

continue; }

returnfalse; }

publicstaticbooleanisTwoPair(Deckd){ Card[]cards=d.cards; int[]counter=newint[13]; for(inti=0;i<cards.length;i++){ counter[cards[i].getRank()]++; }

intpair=0; for(inti=0;i<counter.length;i++){ if(pair==2) returntrue; if(counter[i]==2) pair++; else continue; }

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

if(three&&two) returntrue; if(counter[i]==3) three=true; elseif(counter[i]==2) two=true; else continue; }

returnfalse; }

privatestaticintgetLowestCard(Card[]c,intlow,inthigh){ intmin=low; for(inti=low+1;i<=high;i++){ if(c[i].getRank()<c[min].getRank()) min=i; }

returnmin; }

} 498

latihan12.2s/d12.7kecuali12.5 classDeck{ Card[]cards;

publicDeck(intn){ cards=newCard[n]; }

publicDeck(){ cards=newCard[52]; intindex=0; for(intsuit=0;suit<=3;suit++){ for(intrank=1;rank<=13;rank++){ cards[index]=newCard(suit,rank); index++; } } }

publicstaticDecksubdeck(Deckdeck,intlow,inthigh){ Decksub=newDeck(highlow+1); for(inti=0;i<sub.cards.length;i++) sub.cards[i]=deck.cards[low+i]; returnsub; } 499

publicstaticvoidswapCards(Card[]c,inti,intj){ Cardtemp=c[i]; c[i]=c[j]; c[j]=temp; }

publicstaticvoidshuffleDeck(Card[]c){ for(inti=0;i<c.length;i++){ intrandom=i+(int)(Math.random()*(c.length1)); if(random<=51&&random>=0) swapCards(c,i,random); } }

publicstaticvoidshuffleDeck(Deckd){ for(inti=0;i<d.cards.length;i++){ intrandom=i+(int)(Math.random()*(d.cards.length1)); if(random<=51&&random>=0) } } swapCards(d.cards,i,random);

publicstaticintfindLowestCard(Card[]c,intlow,inthigh){ //if(low<0||high>=c.length) // return99; 500

intmin=low; for(inti=low+1;i<=high;i++){ if(c[min].compareCard(c[i])==1) min=i; } returnmin; }

publicstaticvoidsort(Card[]c){ for(inti=0;i<c.length;i++){ intswap=findLowestCard(c,i,c.length1); if(swap!=99) swapCards(c,i,swap); } }

publicstaticvoidincrementalShuffle(Deckd,Cardc){ intrandom=0+(int)(Math.random()*(d.cards.length1)); d.cards[random]=c; }

publicstaticDeckmerge(Deckd1,Deckd2){

Deckresult=newDeck(d1.cards.length+d2.cards.length); inti=0; intj=0; 501

for(intk=0;k<result.cards.length;k++){

//d1empty if(i==d1.cards.length){ result.cards[k]=d2.cards[j]; j++; //d2empty }elseif(j==d2.cards.length){ result.cards[k]=d1.cards[i]; i++;

}elseif(d1.cards[i].compareCard(d2.cards[j])==1){ result.cards[k]=d1.cards[i]; i++; }else{ result.cards[k]=d2.cards[j]; j++; }

} returnresult; }

502

publicstaticDeckmergeSort1(Deckdeck){

intmid=(deck.cards.length1)/2;

Decksub1=subdeck(deck,0,mid); Decksub2=subdeck(deck,mid+1,deck.cards.length1); sort(sub1.cards); sort(sub2.cards); Deckd=merge(sub1,sub2); returnd;

publicstaticDeckmergeSort2(Deckdeck){ if(deck.cards.length<=1) returndeck; intmid=(deck.cards.length1)/2;

Decksub1=subdeck(deck,0,mid); Decksub2=subdeck(deck,mid+1,deck.cards.length1); sub1=mergeSort2(sub1); sub2=mergeSort2(sub2); Deckd=merge(sub1,sub2); returnd; }

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

publicdoubleabs(){ returnMath.sqrt(real*real+imag*imag); } 504

latihan13.3 publicstaticbooleanequals(Complexa,Complexb){ return(a.real==b.real&&a.imag==b.imag); }

latihan13.4 classComplex{ doublereal; doubleimag;

publicComplex(){ real=0; imag=0; }

publicComplex(doubler,doublei){ real=r; imag=i; }

publicvoidprintComplex(){ System.out.println(real+"+"+imag+"i"); }

publicvoidconjugate(){ 505

imag=imag; }

publicdoubleabs(){ returnMath.sqrt(real*real+imag*imag); } publicstaticComplexnormalize(Complexnum){ doubled=num.abs(); doublereal=num.real/d; doubleimag=num.imag/d; Complexc=newComplex(real,imag); returnc; }

publicvoidadd(Complexx){ real=real+x.real; imag=imag+x.imag; }

publicstaticvoidmain(String[]args){ Complexx=newComplex(); x.real=1; x.imag=2;

506

Complexy=newComplex(3,4);

System.out.println(y.abs());

x.conjugate(); x.printComplex(); y.printComplex();

x.add(y); x.printComplex(); } }

Bab14
latihan14.1 publicclassIntList{ intlength; Nodehead;

publicIntList(){ length=0; head=null; }

publicstaticNoderemoveSecond(Nodelist){ Nodefirst=list; 507

Nodesecond=list.next;

//makethefirstnoderefertothethird first.next=second.next;

//separatethesecondnodefromtherestofthelist second.next=null; returnsecond; }

publicNoderemoveFirst(){ if(head!=null){ NodeheadLama=head; head=head.next; headLama.next=null; length; returnheadLama; } returnnull; }

publicvoidset(intindex,intcargo){ if(index>=1&&index<=length){ inti=1; Nodelist=head; 508

while(i<index){ list=list.next; i++; } list.cargo=cargo; } }

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++; } }

publicvoidaddLast(intcargo){ NodenewNode=newNode(); 509

newNode.cargo=cargo; inti=1; Nodelist=head; while(list.next!=null){ list=list.next; } 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

publicvoidappend(IntListlist){ Nodenode=list.head; while(node!=null){ addLast(node.cargo); node=node.next; }

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

//print:printthelist publicvoidprint(){ Nodenode;

System.out.print("(");

//startatthebeginningofthelist node=head;

//traversethelist,printingeachelement while(node!=null){ System.out.print(node.cargo); node=node.next; if(node!=null){ System.out.print(","); } }

System.out.println(")"); }

publicvoidprintBackward(){ System.out.print("(");

if(head!=null){ 512

Nodetail=head.next; Node.printBackward(tail); System.out.print(head); } System.out.println(")"); }

publicstaticvoidmain(String[]args){

//note:thefollowingisareallybadwaytobuildalist. //warningsignsofbadness:allocatingtwodifferentkinds //ofobjects,accessingtheinstancevariablesofanotherclass, //usingtheconstant3tosetthelength

//createanemptylist IntListlist=newIntList();

//createthreenewnodes,unlinked Nodenode1=newNode(); node1.cargo=1;

Nodenode2=newNode(); node2.cargo=2;

Nodenode3=newNode(); node3.cargo=3; 513

//nextupthenodes node1.next=node2; node2.next=node3; node3.next=null;

list.head=node1; list.length=3;

list.print(); Noderemoved=list.removeFirst(); System.out.println("Nodeyangdihapus"); Node.printList(removed);

list.print(); System.out.println("ubahcargoindeks2jadi6"); list.set(2,6); list.print();

System.out.println("tambahnodedengankargo5dibelakangnodeindekske 1"); list.add(1,5); list.print();

System.out.println("tambahnode7dibelakanglist"); list.addLast(7); 514

list.print();

System.out.println("Reserve"); list.reverse(); list.print();

IntListlist2=newIntList();

//createthreenewnodes,unlinked Nodenode4=newNode(); node4.cargo=4;

Nodenode5=newNode(); node5.cargo=5;

Nodenode6=newNode(); node6.cargo=6;

//nextupthenodes node4.next=node5; node5.next=node6; node6.next=null;

list2.head=node4; list2.length=3;

515

System.out.println("appendlist456"); list.append(list2); list.print(); System.out.println("Checklength="+list.checkLength());

} }

classNode{ intcargo; Nodenext;

//defaultconstructor publicNode(){ cargo=0; next=null; }

//otherconstructor publicNode(intcargo,Nodenext){ this.cargo=cargo; this.next=next; }

publicStringtoString(){ returncargo+""; 516

publicstaticvoidprintBackward(Nodelist){ if(list==null)return;

Nodehead=list; Nodetail=list.next;

printBackward(tail); System.out.print(head+","); }

publicstaticvoidprintList(Nodelist){ Nodenode=list; while(node!=null){ System.out.print(node); node=node.next; }

System.out.println(); } }

//Thisprogramispartof"Howtothinklikeacomputerscientist," //byAllenB.Downey,whichisavailablefromthinkAPjava.com

//ThisprogramislicensedundertheGNUFreeSoftwareLicense, 517

//thetermsofwhichareavailablefromwww.gnu.org

latihan14.2 classPembandingAngka{ publicstaticvoidmain(String[]args){ IntListlist=newIntList(); Nodenode1=newNode(); node1.cargo=3;

Nodenode2=newNode(); node2.cargo=2;

Nodenode3=newNode(); node3.cargo=1;

//nextupthenodes node1.next=node2; node2.next=node3; node3.next=null;

list.head=node1; list.length=3;

IntListlist2=newIntList();

Nodenode4=newNode(); 518

node4.cargo=2;

Nodenode5=newNode(); node5.cargo=6;

Nodenode6=newNode(); node6.cargo=1;

//nextupthenodes node4.next=node5; node5.next=node6; node6.next=null;

list2.head=node4; list2.length=3;

System.out.println("hasil="+compare(list,list2));

publicstaticintcompare(IntListlist1,IntListlist2){ if(list1.length>list2.length) return1; elseif(list1.length<list2.length) return1; else{ 519

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

Stackstack=newStack(); for(inti=0;i<arr.length;i++){ stack.push(Integer.valueOf(arr[i])); } intindeks=0; while(!stack.isEmpty()){ Integeri=(Integer)stack.pop(); arr[indeks]=i.intValue(); indeks++; }

publicstaticvoidmain(String[]args){ intarr[]={3,4,5,6}; Latihan15_1.reverse(arr); for(inti=0;i<arr.length;i++){ System.out.print(arr[i]+""); } } }

Latihan15.2 publicclassLinkedList{ intlength; Nodehead; 521

publicLinkedList(){ length=0; head=null; }

publicstaticNoderemoveSecond(Nodelist){ Nodefirst=list; Nodesecond=list.next;

//makethefirstnoderefertothethird first.next=second.next;

//separatethesecondnodefromtherestofthelist second.next=null; returnsecond; }

//print:printthelist publicvoidprint(){ Nodenode;

System.out.print("(");

//startatthebeginningofthelist node=head; 522

//traversethelist,printingeachelement while(node!=null){ System.out.print(node.cargo); node=node.next; if(node!=null){ System.out.print(","); } }

System.out.println(")"); }

publicvoidprintBackward(){ System.out.print("(");

if(head!=null){ Nodetail=head.next; Node.printBackward(tail); System.out.print(head); } System.out.println(")"); }

publicNoderemoveFirst(){ if(head!=null){ 523

NodeheadLama=head; head=head.next; headLama.next=null; length; returnheadLama; } returnnull; }

publicvoidaddFirst(Objectcargo){ NodenewNode=newNode(); newNode.cargo=cargo; if(head==null){ head=newNode; newNode.next=null; length++; } else{ newNode.next=head; head=newNode; length++; }

524

publicvoidadd(intindex,Objectcargo){ NodenewNode=newNode(); newNode.cargo=cargo; if(head==null){ head=newNode; newNode.next=null; length++; }

elseif(index>=1&&index<=length){ inti=1; Nodelist=head; while(i<index){ list=list.next; i++; } newNode.next=list.next; list.next=newNode; length++; } }

publicstaticLinkedListsplit(Stringsentence){ String[]word=sentence.split(""); Node[]node=newNode[word.length]; for(inti=0;i<word.length;i++){ 525

node[i]=newNode(); node[i].cargo=word[i]; }

LinkedListlist=newLinkedList(); list.head=node[0]; for(inti=1;i<node.length;i++) node[i1].next=node[i]; node[node.length1]=null; list.length=word.length; returnlist; }

publicstaticStringjoin(LinkedListlist){ Nodenode=list.head; Stringresult=""; while(node!=null){ result+=node.cargo+""; node=node.next; } returnresult; }

publicStringtoString(){ returnLinkedList.join(this); } 526

publicstaticvoidmain(String[]args){

//note:thefollowingisareallybadwaytobuildalist. //warningsignsofbadness:allocatingtwodifferentkinds //ofobjects,accessingtheinstancevariablesofanotherclass, //usingtheconstant3tosetthelength

//createanemptylist LinkedListlist=newLinkedList();

//createthreenewnodes,unlinked Nodenode1=newNode(); node1.cargo=newInteger(1);

Nodenode2=newNode(); node2.cargo=newInteger(2);

Nodenode3=newNode(); node3.cargo=newInteger(3);

//nextupthenodes node1.next=node2; node2.next=node3; node3.next=null;

527

list.head=node1; list.length=3;

list.print(); list.printBackward();

LinkedListlinkedList=LinkedList.split("aaaakbfkjfblijndnd"); linkedList.print(); System.out.println(LinkedList.join(linkedList)); System.out.println("TesttoStringmethod"); System.out.println(linkedList.toString()); } }

classNode{ Objectcargo; Nodenext;

//defaultconstructor publicNode(){ cargo=newInteger(0); next=null; }

//otherconstructor publicNode(Objectcargo,Nodenext){ 528

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+","); } }

Latihan15.3 classNewStack{ privateLinkedListlist;

publicNewStack(){ list=newLinkedList(); list.head=null; 529

list.length=0; }

publicbooleanisEmpty(){ returnlist.head==null; }

publicvoidpush(Objecto){ list.addFirst(o); }

publicObjectpop(){ Nodenode=list.removeFirst(); returnnode.cargo; }

publicstaticvoidmain(String[]args){ NewStackstack=newNewStack(); stack.push(Integer.valueOf(1)); stack.push(Integer.valueOf(2)); stack.push(Integer.valueOf(3)); while(!stack.isEmpty()){ Objecto=stack.pop(); System.out.println(o); } } 530

latihan15.4 importjava.util.*; importjava.io.*;

classBalance{ privateStackparenthesStack; privateStackbracketStack; privateStacksquigStack;

publicBalance(){ parenthesStack=newStack(); bracketStack=newStack(); squigStack=newStack();

publicbooleanread(Stringfilename){

BufferedReaderreader=null; try{ reader=newBufferedReader(newFileReader(filename)); while(true){ Strings=reader.readLine(); 531

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

returnfalse; else squigStack.pop(); } } }syst if(squigStack.isEmpty()&&bracketStack.isEmpty()&& parenthesStack.isEmpty()) returntrue; else returnfalse;

}catch(Exceptione){ e.printStackTrace(); returnfalse; }finally{ try{ reader.close(); }catch(IOExceptionioe){ ioe.printStackTrace(); } }

publicstaticvoidmain(String[]args){ 533

System.out.println(newBalance().read("balance")); } }

latihan15.5dan15.6 importjava.util.*; importjava.io.*;

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);

}catch(NumberFormatExceptione){ doubleangka1=((Double)stack.pop()).doubleValue(); doubleangka2=((Double)stack.pop()).doubleValue(); if(operand.equals("+")) stack.push(Double.valueOf(angka1+angka2)); elseif(operand.equals("")) stack.push(Double.valueOf(angka1angka2)); 534

elseif(operand.equals("*")) stack.push(Double.valueOf(angka1*angka2)); elseif(operand.equals("/")) stack.push(Double.valueOf(angka1/angka2)); } } return((Double)stack.pop()).doubleValue(); }

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;

publicstaticbooleanisOperand(Strings){ try{ Integer.parseInt(s); returntrue; }catch(NumberFormatExceptione){ returnfalse; }

536

publicstaticvoidmain(String[]args){ Strings="";

try{ s=inputLoop(); }catch(IOExceptione){ e.printStackTrace(); } System.out.println(s); System.out.println(evalPostFix(s)); } }

Bab16
latihan16.1 classQueue16_1{ publicObject[]array; publicintfirst,next;

publicQueue16_1(){ array=newObject[128]; first=0; next=0; }

537

publicbooleanisEmpty(){ returnfirst==next; }

publicvoidadd(Objectitem){ array[next]=item; next++; }

publicObjectremove(){ if(isEmpty()) returnnull; else{ Objectresult=array[first]; first++; returnresult; } } }

latihan16.2 classQueue16_2{ publicObject[]array; publicintfirst,next;

publicQueue16_2(){ 538

array=newObject[3]; first=0; next=0; }

publicbooleanisEmpty(){ returnfirst==next; }

publicvoidadd(Objectitem){ array[next]=item; if(isFull()) resize_array(); next=(next+1)%array.length; }

privatebooleanisFull(){ return((next+1)%array.length==first); }

privatevoidresize_array(){ Object[]temp=array; array=newObject[2*temp.length]; for(inti=0;i<temp.length;i++){ array[i]=temp[i]; } 539

publicObjectremove(){ if(isEmpty()) returnnull; else{ Objectresult=array[first]; first++; returnresult; } }

publicstaticvoidmain(String[]args){ Queue16_2queue=newQueue16_2(); queue.add("a"); queue.add("b"); queue.add("b"); queue.remove(); queue.add("a"); queue.add("c"); } }

latihan16.4 importjava.util.*; 540

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

publicstaticvoidmain(String[]args){ SortedListlist=newSortedList(); list.add(newNode(6)); list.add(newNode(4)); list.add(newNode(5)); list.print();

latihan16.5 publicObjectmaximum(){ Nodenode=head; Nodemax=head; while(node!=null){ if(max.compareTo(node)==1) max=node; node=node.next; } returnmax; }

latihan16.6 //descendingpriority classPriorityQueueextendsSortedList{ 542

publicbooleanisEmpty(){ returnsuper.isEmpty(); }

publicvoidadd(inta){ Noden=newNode(a); super.add(n); }

publicintremove(){ Nodenode=super.removeLast(); return((Integer)node.cargo).intValue(); }

publicstaticvoidmain(String[]args){ PriorityQueuequeue=newPriorityQueue(); queue.add(6); queue.add(4); queue.add(7); while(!queue.isEmpty()){ System.out.println(queue.remove()); }

} 543

latihan16.7 importjava.util.PriorityQueue; importjava.util.Date;

classEvent{ privatePriorityQueuequeue;

publicbooleanisEmpty(){ returnqueue.size()==0; } publicEvent(){ queue=newPriorityQueue(); }

publicvoidadd(Dated){ queue.add(d); }

publicDatenextTime(){ if(queue.isEmpty()) returnnull; else{ return(Date)queue.peek(); 544

} }

publicDatenextEvent(){ if(queue.isEmpty()) returnnull; else{ return(Date)queue.poll(); } }

publicstaticvoidmain(String[]args){ Eventevent=newEvent(); event.add(newDate(2006,10,6)); event.add(newDate(2006,11,6)); event.add(newDate(2006,10,7)); while(!event.isEmpty()){ System.out.println(event.nextTime().toString()); System.out.println(event.nextEvent().toString()); }

} }

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(); }

privateVectorbuildVector(Treet){ Vectorv=newVector(); v.add(t.getNode().getCargo()); if(t.left!=null) v.addAll(buildVector(t.left)); if(t.right!=null) v.addAll(buildVector(t.right)); returnv; } }

importjava.util.*;

classTree{

publicNodenode; publicTreeleft; 547

publicTreeright;

publicTree(Nodenode,Treeleft,Treeright){ this.node=node; this.left=left; this.right=right; }

publicNodegetNode(){ returnnode; }

publicstaticvoidvisitPreorder(Treetree){ if(tree==null) return; tree.node.visit(); visitPreorder(tree.left); visitPreorder(tree.right); }

publicPreIteratorpreorderIterator(){ returnnewPreIterator(this); }

publicstaticintlongestPath(Treetree){ 548

if(tree==null) return0; return1+Math.max(longestPath(tree.left),longestPath(tree.right)); }

publicstaticvoidmain(String[]args){

Treet1=newTree(newNode(2),null,null); Treet2=newTree(newNode(3),null,null); Treet=newTree(newNode(1),t1,t2); Treet3=newTree(newNode(4),null,null); Treeroot=newTree(newNode(5),t,t3); visitPreorder(root);

PreIteratoriter=root.preorderIterator(); System.out.println(); while(iter.hasNext()){ System.out.println(iter.next()); }

System.out.println("panjangtree"+longestPath(root));

} }

549

classNodeimplementsVisitable,Comparable{ privateObjectcargo; publicNode(Objecto){ cargo=o; }

publicvoidvisit(){ System.out.print(cargo+""); }

publicObjectgetCargo(){ returncargo; }

publicintcompareTo(Objectobj){ Nodenode=(Node)obj; inta=((Integer)this.cargo).intValue(); intb=((Integer)node.cargo).intValue();

if(a>b) return1; if(a<b) return1; return0; } } 550

interfaceVisitable{ publicvoidvisit(); }

latihan17.3 a.9 b.23*1+ c.3

latihan17.4 publicstaticintlongestPath(Treetree){ if(tree==null) return0; return1+Math.max(longestPath(tree.left),longestPath(tree.right)); }

latihan17.5 importjava.util.*;

classComparableTree{ Comparablenode; publicTreeleft; publicTreeright;

publicComparableTree(Comparablenode,Treeleft,Treeright){ 551

this.node=node; this.left=left; this.right=right; }

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){

Treet1=newTree(newNode(2),null,null); Treet2=newTree(newNode(78),null,null); 552

Treet=newTree(newNode(1),t1,t2); Treet3=newTree(newNode(4),null,null); Treeroot=newTree(newNode(5),t,t3);

System.out.println("max="+findMax(root).getCargo());

latihan17.6 importjava.util.*;

classSearchTree{ Comparablenode; publicSearchTreeleft; publicSearchTreeright;

publicSearchTree(Comparablenode,SearchTreeleft,SearchTreeright){ this.node=node; this.left=left; this.right=right; }

publicbooleancontains(Objecto){ returncontains(o,this); 553

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); } }

publicstaticvoidmain(String[]args){ SearchTreet1=newSearchTree(newNode(2),null,null); SearchTreet2=newSearchTree(newNode(4),null,null); SearchTreet=newSearchTree(newNode(3),t1,t2); 554

SearchTreet3=newSearchTree(newNode(6),null,null); SearchTreeroot=newSearchTree(newNode(5),t,t3); System.out.println(root.contains(newNode(5))); } }

latihan17.817.9

importjava.util.*;

classTreeSetModifyextendsTreeSet{ publicstaticTreeSetunion(Setset1,Setset2){ Iteratoriter1=set1.iterator(); Iteratoriter2=set2.iterator();

TreeSetnewset=newTreeSet(); while(iter1.hasNext()){ newset.add(iter1.next()); } while(iter2.hasNext()){ newset.add(iter2.next()); }

returnnewset;

} 555

publicstaticTreeSetintersection(Setset1,Setset2){ Iteratoriter1=set1.iterator();

TreeSetnewset=newTreeSet(); while(iter1.hasNext()){ Objecto=(Object)iter1.next(); if(set2.contains(o)) newset.add(o); }

returnnewset; } }

Bab18
latihan18.118.2dan18.7 importjava.util.*;

classHeap{ int[]array; intsize;

publicHeap(){ 556

array=newint[128]; size=0; }

publicvoidprint(){ for(inti=0;i<array.length;i++){ if(array[i]!=0) System.out.println(array[i]); } }

publicObjectgetCargo(inti){ returnarray[i]; }

publicvoidsetCargo(inti,into){ array[i]=o; }

publicintgetLeft(inti){ return2*i; }

publicintgetRight(inti){ return2*i+1; } 557

publicintgetParent(inti){ if(i%2==1) returni/2; else return(i1)/2; }

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

publicvoidremove(intindeks){ intright=getRight(indeks); intleft=getLeft(indeks); //indeksistree'sleaf if(array[right]==0)

array[indeks]=array[right]; array[right]=array[size1]; if(array[indeks]<array[left]){ inttemp=array[indeks]; array[indeks]=array[left]; array[left]=temp; } reheap(left); reheap(right);

privatevoidreheap(intindeks){ if(array[indeks]==0) return; intright=getRight(indeks); intleft=getLeft(indeks); if(array[indeks]<array[left]){ inttemp=array[indeks]; 559

array[indeks]=array[left]; array[left]=temp; } reheap(left); if(array[indeks]<array[right]){ inttemp=array[indeks]; array[indeks]=array[right]; array[right]=temp; } reheap(right); }

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;

publicstaticvoidmain(String[]args){ Heapheap=newHeap(); heap.add(79); heap.add(60); heap.add(65); 561

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{

publicNodenode; publicTreeleft; publicTreeright;

publicTree(Nodenode,Treeleft,Treeright){ this.node=node; this.left=left; this.right=right; 562

publicNodegetNode(){ returnnode; }

publicstaticvoidvisitPreorder(Treetree){ if(tree==null) return; tree.node.visit(); visitPreorder(tree.left); visitPreorder(tree.right); }

publicstaticintlongestPath(Treetree){ if(tree==null) return0; return1+Math.max(longestPath(tree.left),longestPath(tree.right)); }

publicstaticvoidmain(String[]args){

Treet1=newTree(newNode(2),null,null); 563

Treet2=newTree(newNode(3),null,null); Treet=newTree(newNode(1),t1,t2); Treet3=newTree(newNode(4),null,null); Treeroot=newTree(newNode(5),t,t3); visitPreorder(root);

System.out.println("panjangtree"+longestPath(root));

} }

classNodeimplementsVisitable,Comparable{ privateObjectcargo; publicNode(Objecto){ cargo=o; }

publicvoidvisit(){ System.out.print(cargo+""); }

publicObjectgetCargo(){ returncargo; }

564

publicintcompareTo(Objectobj){ Nodenode=(Node)obj; inta=((Integer)this.cargo).intValue(); intb=((Integer)node.cargo).intValue();

if(a>b) return1; if(a<b) return1; return0; } }

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(); }

publicObjectget(Objectkey){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(key.equals(entry.key)){

566

returnentry.value; } } returnnull; }

publicObjectput(Objectkey,Objectvalue){ Objectresult=get(key); if(result==null){ Entryentry=newEntry(key,value); entries.add(entry); }else{ update(key,value); } returnresult; }

privatevoidupdate(Objectkey,Objectvalue){ Iteratorit=entries.iterator(); while(it.hasNext()){ Entryentry=(Entry)it.next(); if(key.equals(entry.key)){ entry.value=value; break; }

567

} }

publicSetkeySet(){ Iteratorit=entries.iterator(); Sets=newTreeSet(); while(it.hasNext()){ Entryentry=(Entry)it.next(); s.add(entry.key); } returns; }

publicbooleancontainsKey(Objectkey){ if(get(key)==null) returnfalse; else returntrue; }

classEntry{ Objectkey,value;

568

publicEntry(Objectkey,Objectvalue){

this.key=key; this.value=value; } publicStringtoString(){

return"{"+key+","+value+"}"; } }

PenggunaanTreeSetpadametodekeySetcukupmudah.Prinsipnyaadalahandatinggal mengambilsemuakunciyangadapadaVectordanmemasukkannyasatupersatuke dalamTreeSet.UntukmelakukanhaliniVectormemilikimetodeiteratoryangbisa digunakanuntukmenjelajahisemuaelemenpadaVector.

Latihan19.2 a123456 b111213141516 c1234566

Latihan19.3 21

Latihan19.5 importjava.util.*;

569

classBirthDay{ privateintday; privateintmonth;

publicBirthDay(intd,intm){ day=d; month=m; } publicintgetDay(){ returnday; }

publicintgetMonth(){ returnmonth; }

publicbooleanequals(BirthDayb){ if(this.day==b.getDay()&&this.month==b.getMonth()){ returntrue; } returnfalse; }

570

publicstaticbooleanhasDuplicate(BirthDay[]arr){ Listlist=newArrayList(); for(inti=0;i<arr.length;i++){ Stringstr=arr[i].getDay()+""+arr[i].getMonth(); if(list.contains(str)) returntrue; else list.add(arr[i]); } returnfalse; }

publicstaticBirthDay[]randomBirthdays(intn){ BirthDay[]bdays=newBirthDay[n]; for(inti=0;i<n;i++){ intday=1+(int)(Math.random()*30); intmonth=1+(int)(Math.random()*12); bdays[i]=newBirthDay(day,month); } returnbdays; }

publicstaticvoidmain(String[]args){ for(inti=1;i<100;i++){ BirthDay[]bday=randomBirthdays(10);

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{

privateBufferedReaderreader; privateMapmap=newHashMap(); privateintnumOfWord;

publicExcercise197(Stringfilename){ try{ reader=newBufferedReader(newInputStreamReader(new FileInputStream(filename))); }catch(Exceptione){ e.printStackTrace();

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));

} }catch(Exceptione){ e.printStackTrace(); try{ reader.close(); }catch(IOExceptionioe){ 574

ioe.printStackTrace(); } } } }

publicintgetNumOfDifferentWord(){ returnmap.size(); }

publicintgetNumOfWord(){ returnnumOfWord; }

publicintgetNumOfWord(Strings){ Objecto=map.get(s); if(o==null) return0; return((Integer)o).intValue(); }

publicString[]get20MostCommonWord(){ Sets=map.keySet(); Iteratoriter=s.iterator(); PriorityQueuequeue=newPriorityQueue(); 575

while(iter.hasNext()){ Stringkey=(String)iter.next(); Pairp=newPair(key,((Integer)map.get(key)).intValue()); queue.add(p); } String[]arr=newString[20]; for(inti=0;i<20;i++){ arr[i]=((Pair)queue.poll()).getWord(); } returnarr;

} /** *@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

String[]arr=e.get20MostCommonWord(); for(inti=0;i<arr.length;i++) System.out.println(arr[i]); }

classPairimplementsComparable{ Stringword; intfrequency;

publicPair(Stringw,intfreq){ word=w; frequency=freq; }

publicintgetFrequency(){ returnfrequency; }

publicStringgetWord(){ returnword; }

publicintcompareTo(Objecto){ 577

Pairp=(Pair)o; if(this.getFrequency()>p.getFrequency()) return1; elseif(this.getFrequency()<p.getFrequency()) return1; else return0; } }

Latihan19.8 importjava.util.*;

publicclassLinkedList{ intlength; Nodehead;

publicLinkedList(){ } //metodeyangmengecekapakahsuatulistmengandungloop publicbooleancontainLoop(){ Nodenode=head; 578 length=0; head=null;

Mapmap=newHashMap(); while(node!=null){ if(map.containsKey(node)) returntrue; else map.put(node,newInteger(1)); node=node.next; }

returnfalse; }

publicstaticvoidmain(String[]args){ LinkedListlist=newLinkedList();

//createthreenewnodes,unlinked Nodenode1=newNode(); node1.cargo=newInteger(1);

Nodenode2=newNode(); node2.cargo=newInteger(5);

Nodenode3=newNode(); node3.cargo=newInteger(3); 579

//nextupthenodes node1.next=node2; node2.next=node3; node3.next=node1;

list.head=node1; list.length=3;

System.out.println(list.containLoop()); }

classNode{ Objectcargo; Nodenext;

//defaultconstructor publicNode(){ cargo=newInteger(0); next=null; } } 580

Latihan19.9 importjava.util.*;

classNewMap{ Vectorentries;

publicNewMap(){ entries=newVector(); }

publicObjectget(Objectkey){ Iteratorit=entries.iterator(); while(it.hasNext()){ java.util.LinkedListentry=(java.util.LinkedList)it.next(); if(key.equals(entry.getFirst())){ returnentry.getLast(); } }

returnnull; }

publicObjectput(Objectkey,Objectvalue){ Objectresult=get(key); 581

if(result==null){ Listl=newjava.util.LinkedList(); l.add(key); l.add(value); entries.add(l); }else{ update(key,value); } returnresult; }

privatevoidupdate(Objectkey,Objectvalue){ Iteratorit=entries.iterator(); while(it.hasNext()){ java.util.LinkedListentry=(java.util.LinkedList)it.next(); if(key.equals(entry.getFirst())){ entry.set(1,value); break; } } }

publicSetkeySet(){ Iteratorit=entries.iterator(); TreeSetset=newTreeSet(); 582

while(it.hasNext()){ java.util.LinkedListentry=(java.util.LinkedList)it.next(); set.add(entry.getFirst()); } returnset; }

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.*;

classNewSet { HashMapmap; publicNewSet(){ map=newHashMap(); }

publicvoidclear(){ map=newHashMap(); }

publicbooleanremove(Objecto){ if(map.remove(o)!=null) returntrue; else returnfalse; }

publicbooleanremoveAll(Collectionc){ Iteratorit=c.iterator();

584

while(it.hasNext()){ if(remove(it.next())) continue; else returnfalse; } returntrue;

publicvoidadd(Objecto){ map.put(o,null); } }

Latihan19.11 UntukmelakukanpengujiansayamenyediakankelasBenchMarkyangmengambil argumenbanyakdata(n)yangakanditestdanmencetakwaktuyangdigunakanoleh HashMapdanTreeMapdalammelakukanoperasiadddancontains. Untukmenggunakankelasandaharusmemberiargumensaatandamengeksekusikelas padakonsoleataucommandprompt

Contohpenggunaan: [fuad@fuadbab19]$javaBencmark200 TESMETODEADD

585

waktuhashmap1 waktutreemap2

TESMETODECONTAINS waktuhashmap1 waktutreemap1 EksekusidiatasakanmengetesHashMapdanTreeMapdengandatasebanyak200. waktuyangdihasilkanadalahwaktueksekusimasingmasingmetodebaikaddmaupun contains.

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

for(inti=1;i<=n;i++) treeMap.put(newInteger(i),"test"); time1=System.currentTimeMillis(); System.out.println("waktutreemap"+(time1time)); }

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));

keys=treeMap.keySet().iterator(); time=System.currentTimeMillis(); while(keys.hasNext()){ treeMap.containsKey(keys.next()); } time1=System.currentTimeMillis(); System.out.println("waktutreemap"+(time1time));

587

publicstaticvoidmain(String[]args){ intn=Integer.parseInt(args[0]); Bencmarkb=newBencmark(); b.add(n); b.testContains(); } }

BAB20

Latihan20.12

importjava.io.BufferedReader; importjava.io.FileInputStream; importjava.io.IOException; importjava.io.InputStreamReader; importjava.util.HashMap; importjava.util.Iterator; importjava.util.Map;

publicclassFreqTabextendsHashMap{ 588

BufferedReaderreader; Mapmap=newHashMap(); publicFreqTab(Stringfilename){ try{ reader=newBufferedReader(newInputStreamReader(new FileInputStream(filename))); }catch(Exceptione){ e.printStackTrace(); } }

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

}catch(Exceptione){ e.printStackTrace(); try{ reader.close(); }catch(IOExceptionioe){ ioe.printStackTrace(); } } } }

privatevoidincrement(charc){ Characterkey=Character.valueOf(Character.toLowerCase(c)); Objecto=map.get(key); if(o==null) map.put(key,newInteger(1)); else{ intoldValue=((Integer)o).intValue(); map.put(key,newInteger(++oldValue));

publicvoidprint(){ 590

Iteratoriter=map.keySet().iterator(); while(iter.hasNext()){ Objectkey=iter.next(); System.out.println(key+""+map.get(key)); }

} publicstaticvoidmain(String[]args){ FreqTabft=newFreqTab("FreqTab.java"); ft.buildFrequencyTable(); ft.print();

} Kelasdiatasmengambilparameternamafilepadakonstruktornya,membacadan menghitungfrekuensikemunculantiaptiaphuruf.Sebagaicontohsayamembacafile kodesumberkelasinilagi. Andabisamengubahnyadengantekslainyangandainginkan.

Latihan20.13 importjava.util.*;

publicclasspairimplementsComparable{ intfrequency;

591

charkarakter;

publicpair(charc,inta){ karakter=c; frequency=a; }

publicpair(){ }

publicintgetFrequency(){ returnfrequency; }

publicchargetKarakter(){ returnkarakter; }

publicintcompareTo(Objecto){ pairp=(pair)o; if(this.getFrequency()>p.getFrequency()) return1; elseif(this.getFrequency()<p.getFrequency()) return1; else

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{

BufferedReaderreader; Mapmap=newHashMap(); publicFreqTab(Stringfilename){ try{ reader=newBufferedReader(newInputStreamReader(new FileInputStream(filename))); }catch(Exceptione){ e.printStackTrace(); } 593

publicFreqTab(){

publicvoidbuildFrequencyTable(Stringteks){ char[]arr=teks.toCharArray(); for(inti=0;i<arr.length;i++){ if(Character.isLetter(arr[i])){ increment(arr[i]); } } }

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

increment(arr[i]); } } }catch(Exceptione){ e.printStackTrace(); try{ reader.close(); }catch(IOExceptionioe){ ioe.printStackTrace(); } } } }

privatevoidincrement(charc){ Characterkey=Character.valueOf(Character.toLowerCase(c)); Objecto=map.get(key); if(o==null) map.put(key,newInteger(1)); else{ intoldValue=((Integer)o).intValue(); map.put(key,newInteger(++oldValue));

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()); } }

publicstaticvoidmain(String[]args){ FreqTabft=newFreqTab("FreqTab.java"); ft.buildFrequencyTable(); ft.print();

596

} Latihan20.14

447 186 261 151 110 e 93 s 71 r 57 t 53 93 n 49 i 44 d 43 80 o 37

latihan20.15

importjava.io.*; importjava.util.*;

publicclassHuffTreeextendspair{ HuffTreeleft,right;

publicHuffTree(charc,inta,HuffTreeleft,HuffTreeright){ super(c,a); 597

this.left=left; this.right=right; }

publicintcompareTo(Objecto){ returnsuper.compareTo(o); }

publicHuffTreegetLeft(){ returnleft; }

publicHuffTreegetRight(){ returnright; }

publicstaticvoidprint(HuffTreetree){ System.out.println(tree.getFrequency()); if(tree.left!=null) print(tree.left); if(tree.right!=null) print(tree.right); }

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

} publicstaticvoidmain(String[]args){ FreqTabft=newFreqTab("FreqTab.java"); ft.buildFrequencyTable(); HuffTreetree=HuffTree.build(ft); HuffTree.print(tree);

} }

Latihan20.16 a.santa b.steere c.deer d.east

Latihan20.17 publicclassHuffMan{ privateHuffTreetree; publicHuffMan(Stringtext){ FreqTabft=newFreqTab(); ft.buildFrequencyTable(text); tree=HuffTree.build(ft); }

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

privateHuffTreeroot; publicCodeTab(HuffTreer){ root=r; }

publicvoidgetCodes(){ traverseTree(root,""); }

privatevoidtraverseTree(HuffTreet,Stringlastpath){ if(t.left==null&&t.right==null){ put(Character.valueOf(t.getKarakter()),lastpath); return; } traverseTree(t.getLeft(),lastpath+"."); traverseTree(t.getRight(),lastpath+""); } }

publicclassHuffMan{ privateHuffTreetree; publicHuffMan(Stringtext){ FreqTabft=newFreqTab(); 602

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; }

publicStringencode(Strings){ char[]charArr=s.toCharArray(); 603

CodeTabct=newCodeTab(tree); ct.getCodes(); Stringcode=""; for(inti=0;i<charArr.length;i++){ ObjectcodePart=ct.get(Character.valueOf(charArr[i])); if(codePart!=null) code+=(String)codePart; } returncode; }

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

for(inti=1;i<=13;i++) teks+="d"; HuffManhm=newHuffMan(teks); Stringcode=hm.encode("desta"); System.out.println(code); System.out.println(hm.decode(code));

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

51 Franklin St, Fifth Floor, Boston, MA

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

Anda mungkin juga menyukai