Jumat, 30 Desember 2011

CLASS COLLECTION DAN CLASS ARRAY

Class Collection berisi method - method utility yang sering digunakan, seperti untuk melakukan sorting, melakukan pencarian, mengacak isi List, membalik susunan List, mengcopy potongan List, mengisi List dengan pola tertentu, dll.

Method sort digunakan untuk mengurutkan list berdasarkan logika yang ada pada method Comparable. Item didalam List harus mengimplementasikan interface Comparable, kalau tidak maka gunakan method sort dengan 2 parameter yaitu List dan Object dari class yang mengimplementasikan interface Comparator.

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class SortListTest{
             public static void main(){
                         List<Customer> customers = new ArrayList<Customer>();
                         Customer c1 = new Customer();
                         c1.setId(10l);
                         customers.add(c1);
                         Customer c2 = new Customer();
                         c2.setId(2l);
                         customers.add(c2);
                         Customer c3 = new Customer();
                         c3.setId(5l);
                         customers.add(c3);
                      
                         System.out.println("Isi dari List sebelum disorting");
                         for(int i=0; i < customers.size(); i++){
                                       Customer current = customers.get(i);
                                       System.out.println("index ke : " + current.getId());
                         }
                      
                         Collections.sort(customers);
                         System.out.println("Isi dari List setelah disorting");
                         for(int i=0; i < customers.size(); i++){
                                        Customer current = customers.get(i);
                                        System.out.println("index ke : " +current.getId());
                         }
             }
}

Isi dari List sebelum disorting
index ke : 10
index ke : 2
index ke : 5
Isi dari List setelah disorting
index ke : 2
index ke : 5
index ke : 10

kalau class Customer tidak mengimplementasikan interface Comparable, dapat dibuat class customerComparator yang mengimplementasikan interaface Comparator, dan menggunakan method sort yang 2 parameter list of customer dan instace dari customerComparator.

Collection.sort(customers, new customerComparator);

import java.util.Comparator;
public class customerComparator implements Comparator<Customer>{
                 public int compare(Customer c1, Customer c2){
                            return c1.getId().compareTo(c2.getId());
                 }

}

method binarySearch digunakan untuk melakukan pencarian isi List lebih cepat ketimbang menggunakan method indexOf dari interface List. Method binarySearch baru bisa dipanggil kalau isi List telah disorting terlebih dahulu. Method binarySearch menggunakan 2 parameter kalau object dalam list mengimplementasikan interface Comparable. List dan item yang ingin dicari.

public class BinarySearchTest{
            public static void main(String[] args){
                       List<Customer> customers = new ArrayList<Customer>();
                       Customer c1 = new Customer();
                       c1.setId(10l);
                       customers.add(c1);
                       Customer c2 = new Customer();
                       c2.setId(2l);
                       customers.add(c2);
                       Customer c3 = new Customer();
                       c3.setId(5l);
                       customers.add(c3);
                       Collections.sort(customers);
                       int index = Collections.binarySearch(customers, c3);
                       System.out.println("Customer dengan id : " + c3.getId() + " ditemukan diindex ke : " + index);
            }
}

Kalau class Customer tidak mengimplementasikan interaface Comparable, buat class baru customerComparator implementasi dari interaface Comparator. method binarySearch menjadi 3 parameter : list of customers, yang ingin dicari, intansi dari class CustomerCompartor

int index = Collections.binarySearch(customers, c3, new CustomerComparator());

Customer dengan id : 5 ditemukan diindex ke : 1

Untuk mengacak isi dari List ada method shuffle, method shuffle ada dua overload yang pertama hanya satu parameter berupa List, yang kedua menggunakan dua parameter berupa List dan object dari class Random, object random digunakan untuk menentukan jenis randomisasi yang ingin digunakan untuk mengacak list.

Method reverse digunakan untuk membalik isi List, yang di depan menjadi dibelakang dan sebalikya. Semakin banyak dari isi List waktu eksekusinya membesar secara linier.

Method copy digunakan untuk mengcopy isi dari List ke List yang lain, method ini dapat menghemat beberapa baris coding ketimbang mengcopy list secara manual menggunakan perulangan.

Method fill digunakan untuk mengganti isi dari sebuah List dengan sebuah object yang sama. Parameter dari method fill ada dua : List dan object item yang akan digunakan untuk menimpa semua isi dari List.

Method min dan max digunakan untuk mendapat nilai minimum dan maximum dari List. Method ini menyarankan isi dari list mengimplementasikan interface Comparable, jika tidak menambah instance dari class yang mengimplementasikan interaface Comparator kedalam method min dan max.

Method unmodifiable ada beberapa jenis: unmodifiableList, unmodifiableMap, unmodifiableSet, unmodifiableCollection digunakan untuk melindungi collection agar tidak dapat di modifikasi, collection akan bersifat read only, sehingga tidak bisa dimodifikasi dari luar class, contoh class Customer mempunyai property email yang bertipe List of  String.

public class Customer {

Selasa, 27 Desember 2011

SORTING

Sorting adalah sebuah cara untuk membuat collection terurut (sorted). Agar collection terurut perlu membuat item yang dimasukkan kedalam Set  mengimplements interface Comparable. Interface ini digunakan untuk membandingkan dua buah object, mana object yang lebih besar, lebih kecil atau sama persis.

Interface Comparable hanya mempunyai satu buah method yaitu compareTo, method ini mempunyai sebuah parameter yang bertipe Object kalau tidak menggunakan generics, dan bertipe sama dengan class yang mengimplementasikan interface Comparable kalau menggunakan generics, kembalian method berupa integer, kalau bernilai positif maka object yang dipanggil method comparenya lebih besar dari object yang dimasukkan ke parameter, nilai kembalian negatif sebaliknya, kalau nilai kembalian nol berarti sama besar.

Implementasi Comparable pada class Customer.

import java.lang.Comparable;
public class Customer implements Comparable{
           private Long id;
           public void setId (Long aId){
                      this.id = aId;
           }
           public Long getId (){
                      return this.id;
           }
           public int compareTo(Object o){
                     Customer c = (Customer) o;
                     return getId().compareTo(c.getId());
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }
}

Kalau menggunakan generics maka parameter method compareTo bukan bertipe Object melainkan Customer.

import java.lang.Comparable;
public class Customer implements Comparable<Customer>{
           private Long id;
           public void setId (Long aId){
                      this.id = aId;
           }
           public Long getId (){
                      return this.id;
           }

           public int compareTo(Customer c){
                      return getId().compareTo(c.getId());
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }
}

perbandingan dalam method compareTo akan mengurutkan dari id yang kecil ke besar, jika ingin mengurutkan dari id besar ke kecil tinggal dibalik perbandingannya.

public int compareTo(Customer c){
            return c.getId().compareTo(getId());
}

Interface Comparable seperti diatas bisa dilakukan kalau source codenya tersedia misal source code Costumer dapat dimodifikasi class Customer, kalau misalnya class yang ingin diurutkan tidak tersedia source codenya, dapat dilakukan dengan membuat class baru yang meng extends class tersebut sekaligus implements dari class Comparable, sehingga dapat membuat terurut dari class tersebut, kalau classnya berbentuk final yang tidak mungkin di extends dapat dibuat class baru yang implements interface Comparable.

import java.lang.Comparable;
public class CustomerComparable extends Customer implements Comparable<Customer>{
            public int compareTo(Customer c){
                           return getId().compareTo(c.getId());
            }
}

Interface Comparator mempunyai bentuk generics dan bentuk bukan generics, bentuk generics parameter methodnya sudah menjadi class Customer, sedangkan bentuk bukan generics parameternya berbentuk class Object sehingga memerlukan casting untuk diubah menjadi class Customer.

import java.util.Comparator;
public class CustomerComparator implements Comparator<Customer>{
               public  int compare(Customer c1, Customer c2){
                           return c1.getId().compareTo(c2.getId());
               }
}

Setelah Customer mengimplementasi Comparable dapat digunakan collection terurut seperti TreeSet dan TreeMap.

import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;

public class CustomerTreeSetTest{
            public static void main(String[] args){
                        Set<Customer> customers = new TreeSet<Customer>();
                        Customer c1 = new Customer();
                        c1.setId(1l);  
                        customers.add(c1);
                        Customer c2 = new Customer();
                        c2.setId(2l);
                        customers.add(c2);
                        Customer c = new Customer();
                        c.setId(1l);
                        customers.add(c) // akan direplace yang lama dengan ini
                        Iterator<Customer> iterator = customers.iterator();
                        while(iterator.hasNext()){
                                  Customer current = iterator.next();
                                  System.out.println("Keranjang no - " + current.hashCode() + " id :  " + current.getId());
                        }
            } 
}

Keranjang no - 372 id :  1
Keranjang no - 373 id :  2

TreeSet dan TreeMap mengharuskan item yang dimasukkan mengimplementasikan Comparable. kalau tidak mengimplementasikan buat class Comparator baru yang mengimplementasikan Comparator dan memasukkan object dari class Comparator tersebut kedalam constructor dari TreeSet dan TreeMap tersebut.

Set<Customer> customers = new TreeSet<Customer>(new CustomerComparator());
Map<Customer> customerMaps = new TreeMap<Customer>(new CustomerComparator());

MAP

Map adalah bentuk struktur data yang berpasangan antara key-value. Key bersifat unik karena implementasi menggunakan Set. Key dan value adalah object, bisa object apa saja, tipe data primitif tidak bisa dimasukkan kedalam Map, juga tidak bisa dimasukkan kedalam semua jenis collection.

Implementasi Map memberi kesempatan untuk mencari value berdasarkan key. Setiap dihadapi masalah pencarian berdasarkan value dapat digunakan Map. Map tergantung method equals dan hashCode untuk menentukan apakah dua buah key sama atau tidak, jadi kalau ingin menggunakan object dari class buatan sendiri sebagai key, maka kedua object tersebut harus dioverride untuk menentukan bagaimana kedua object dianggap sama atau tidak.

HashMap adalah class yang mengimplementasikan interface Map. Sifatnya adalah tidak terurut tidak teratur. Implementasi HashMap adalah yang paling efesien implementasi yang lain membutuhkan keteraturan dan keteruturan yang akan menambah komputing sehingga kurang efisien dibandingkan HashMap. HashMap membolehkan satu buah key dengan nilai null dan banyak key bukan null yang valuenya adalah null.

method penting yang dimiliki Map
put (Object key, Object value) method yang digunakan untuk meletakkan pasangan key dengan value.
getObject(Object key) method yang digunakan untuk mendapatkan value dari key yang dimasukkan sebagai parameter.
keySet(); digunakan untuk mendapatkan Set yang berisi semua key, digunakan untuk mendapatkan Set dari key untuk mengambil nilai Map satu per satu.

Membuat Map dimana key adalah kota dan valuenya adalah kumpulan customer yang tinggal di kota tersebut.. Tipe data key adalah String dan tipe data value adalah List of Customer.

import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

public class MapTest{
           public static void main (String[] args){
                      Map<String, List<Customer>> customerByCityMap = new HashMap<String, List<Customer>>();
                       List<Customer> jakartaCust = new ArrayList<Customer>();
                       Customer a = new Customer();
                       a.setId(1l);
                       jakartaCust.add(a);
                       Customer b = new Customer();
                       b.setId(2l);
                       jakartaCust.add(b);
                       customerByCityMap.put("Jakarta",jakartaCust);
                       List<Customer> surabayaCust = new ArrayList<Customer>();
                       Customer c= new Customer();
                       c.setId(3l);
                       surabayaCust.add(c);
                       customerByCityMap.put("Surabaya",surabayaCust);
                       Set<String> keys = customerByCityMap.keySet();
                       Iterator<String> iterator = keys.iterator();
                       while(iterator.hasNext()){
                                String key = iterator.next();
                                List<Customer> customers = customerByCityMap.get(key);
                                for(int i = 0; i < customers.size(); i++){
                                        Customer cust = customers.get(i);
                                        System.out.println ("kota " + key + " customer " + cust.getId());
                                }
                       }
           }
 
}

kota Jakarta customer 1
kota Jakarta customer 2
kota Surabaya customer 3

SET

Set adalah collection yang bersifat unik, arti unik adalah dengan mengoverride method equals dah hashCode dari class yang akan dimasukkan dalam Set. Semua class wrapper seperti String telah mengoverride method equals dan hashCode, sehingga dua buah object dianggap sama jika string didalamnya sama. Untuk class yang dibuat sendiri seperti class Customer maka method equals dan hashCode harus di override dahulu sebelum dimasukkan kedalam Set, kalau tidak dioverride maka kedua object dianggap sama jika mempunya reference ke object yang sama ( tidak sesuai harapan ).

Class implementasi dari interface Set yang paling sering digunakan adalah HashSet. Nilai kembalian dari method hashCode sangat penting dalam class HashSet karena digunakan untuk menentukan dimana object tersebut diletakkan pada HashSet. Ketika method add dipanggil dengan parameter object, HashSet akan memanggil method hashCode dari object tersebut untuk menentukan di keranjang mana object tersebut akan diletakkan. Setelah menemukan nomor keranjangnya maka dicek apakah keranjang tersebut kosong atau tidak. Kalau kosong maka object akan langsung diletakkan pada keranjang tersebut. Kalau keranjang ada isinya maka dilakukan pengetesan dengan method equals, kalau ada object dalam keranjangan dilakukan pengetesan dengan method equals menghasilkan true, maka object lama akan ditimpa dengan object baru.

Kecepatan pencarian pada HashSet tergantung dari perhitungan hashCode, Kalau method hashCode selalu return 1 maka object dalam keranjang HashSet akan diletakkan pada keranjang yang sama sehingga pencarian menjadi linier karena akan dibandingkan isinya dengan method equals satu per satu. Kalau setiap object memiliki hashCode yang unik maka pencarian akan cepat.

Kalau nilai hashCode tidak selalu unik. HashSet akan melihat isi dalam keranjang, kalau ada satu object maka object tersebut merupakan kembalian pencarian, kalau tidak ada object maka kembaliannya null, kalau ada beberapa object maka akan ditest menggunakan method equals, ketika method equals menghasilkan true maka object tersebut adalah hasil pencarian.

Jika dua buah object dipanggil method equals menghasilkan nilai true tetapi hashCodenya berbeda (menyalahi aturan), maka hashSet kedua object ini dianggap berbeda karena diletakkan pada keranjang yang berbeda karenak keranjangnya berbeda maka method equals akan diabaikan, tidak pernah dipanggil. Jadi harus ditaati kalau dua object dioperasikan dengan method equals menghasilkan kembalikan true, maka hashCodenya harus berbeda.


Keranjang           1         2         3
                           "a"      "b"      "ab"
                                                 "ba"

Algoritma sederhana menghitung hashCode dari class String adalah dengan menambahkan urutan dari huruf misal, String "a" nilai hashCodenya 1, String "b" nilai hashCodenya 2, String "ab" dan "ba" nilai hashCodenya 3, string "ab" dan "ba" diletakkan pada keranjang yang sama karena nilai hashCodenya sama tetapi tidak ditimpa karena "ab".equals("ba") menghasilkan false.

import java.util.*;
public class CustomerSetTest{
              public static void main(String[] args){
                         Set<Customer> customers = new HashSet<Customer>();
                         Customer id1 = new Customer();
                         id1.setId(1l);
                         customers.add(id1);
                         Customer id2 = new Customer();
                         id2.setId(2l);
                         customers.add(id2);
                         Customer c = new Customer();
                         c.setId(1l);
                         customers.add(c); // mereplace id 1 karena no idnya sama
                         Iterator<Customer> i = customers.iterator();
                         while(i.hasNext()){
                                   Customer current = i.next();
                                   System.out.println("Keranjang no- " + current.hashCode() + " idnya : " + current.getId() );
                         }
              }
}

Keranjang no- 373 idnya : 2
Keranjang no- 372 idnya : 1

no keranjang tidak berurut dari kecil ke besar, HashSet hanya menekankan pada sifat yang unik saja, sedangkan urutan dan keteraturan tidak dijamin.

LIST

List adalah jenis collection yang teratur (ordered) tetapi tidak terurut (unsorted). List memiliki index yang disusun beradasarkan kapan item dimasukkan kedalam List. Isi dari list bersifat tidak unik, artinya dua buah item yang sama bisa dimasukkan berkali - kali kedalam List. Method penting didalam list

get (int index) : method ini digunakan untuk mengambil isi dari list berdasarkan index (urutan item masuk ke dalam List)
indexOf (Object o) : method ini digunakan untuk mengetahui berapa nomor index dari object yang ada didalam list.
add (Object o) : method ini digunakan untuk menanmbakan object kedalam List
add (int index, Object o) : menambahkan object kedalam List di index tertentu.

Class ArrayList adalah Class yang mengimplementasikan interface List, class ArrayList adalah Array yang dapat bertambah ukurannya. Vector adalah class juga yang mengimplementasikan interface List. Vector adalah pendahulu ArrayList yang performannya kurang baik.

LinkedList adalah implementasi dari interface List yang menambah method baru untuk menambah atau menghapus isi dari List dari depan atau dari belakang, cocok digunakan untuk membuat tumpukan (stack) ,  antrian (queue)

import java.util.*;
public class ListTest {
           public static void main (String[] args){
                    List<String> list = new ArrayList<String>();
                    list.add("a");
                    list.add("b");
                    list.add("c");
                    list.add("a");
                    list.add("z");
                    System.out.println("Isi dari list adalah ");
                    for(int i=0; i < list.size(); i++){
                              System.out.println("isi index ke - "+i +" = " +list.get(i));
                    }
          }
}

Isi dari list adalah
isi index ke - 0 = a
isi index ke - 1 = b
isi index ke - 2 = c
isi index ke - 3 = a
isi index ke - 4 = z

item dalam list / isi list tidak unik bisa double dan juga tidak terurut, hanya teratur sesuai index yang dimasukkan terlebih dahuli.

Senin, 26 Desember 2011

JAVA COLLECTION FRAMEWORK

Dalam Java Collection API ada beberapa interface kunci yang merupakan dasar dari collection yang ada dalam interface

Collection                Set                                     SortedSet
List                          Map                                   SortedMap
Queue                      NavigableSet                    NavigableMap

Map, Set, List, Queue diimplementasikan oleh clas

Map                          Set                            List                        Queue
HashMap                 HashSet                    ArrayList               PriorityQueue
HashTable                LinkedHashSet         Vector
TreeMap                  TreeSet                      LinkedList
LinkedHashMap

Setiap jenis collection diatas mempunya 4 variant, terurut (sorted), tidak terurut, teratur (ordered), tidak teratur.

Terurut artinya isi collection tersebut terurut berdasarkan nilai tertentu dari objectnya, contohnya class Customer terurut berdasarkan id, atau property lain di dalam class Customer.

Teratur adalah collection yang diatur berdasarkan kapan item tersebut dimasukkan kedalam collection, item yang dimasukkan pertama akan berada diawal collection, item yang dimasukkan terakhir akan berada di akhir collection

Kamis, 22 Desember 2011

EQUALS DAN HASHCODE

method equals dan hashcode berperan sangat penting dalam collection. Method equals digunakan untuk membandingkan dua buah object apakan sama atau tidak secara logis. Operator == dapat digunakan untuk membandingkan dua buah  object, tetapi perbandingan ini hanya menghasilkan nilai yang true kalau dua buah object apakah berada dalam memory yang sama, atau bisa dibilang dua buah object mempunyai reference yang sama persis, baik secara alamat memory dan otomatis sama secara logis.

Method equals akan mengembalikan nilai true kalau kedua object sama secara logis walaupun kedua object mempunyai reference yang berbeda (tidak berada di memory yang sama). Contoh String, dua buah object string akan menghasilkan false jika dioperasiakan dengan == walaupun string didalamnya sama. Tetapi method equals akan menghasilkan nilai true walaupun objectnya berada didalam memory yang berbeda asalkan nilai stringnya sama.

public class EqualsTest{
            public static void main(String[] args){
                         String abc = new String("abc");
                         String abc1 = new String("abc");
                         boolean equalsOperator = (abc == abc1);
                         System.out.println("abc == abc ? " + equalsOperator);
                         boolean equalsMethod = abc.equals(abc1);
                         System.out.println("abc.equals(abc) ? " + equalsMethod);
             }
}

abc == abc ? false
abc.equals(abc) ? true

Jika kita ingin membandingkan dua buah object apakah sama secara logis, kita akan menggunakan method equals, tetapi masalahnya implementasi method equals dari class Object sama persis dengan menggunakan operator ==, sehingga harus di override agar walau dua buah object yang berbeda tetap dianggap sama asalkan suatu kriteria terpenuhi.

Misalkan class Customer, dua buah object customer dianggap sama asalkan idnya sama, oleh karena itu method equals dioverride

public class Customer{
           private Long id;
           public void setId (Long aId){
                      this.id = aid;
           }
           public Long getId (){
                      return this.id;
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
}

method hashCode akan mengembalikan nilai integer yang unik untuk setiap object yang berbeda 

method hashCode dari sebuah object harus mengembalikan nilai yang sama walaupun dieksekusi berkali kali selama nilai property didalamnya tidak berubah.
Kalau dua buah object dioperasikan dengan method equals mengembalikan nilai true maka method hashCode dari kedua object harus mengembalikan nilai integer yang sama. Sebaliknya kalau dua buah object mengembalikan nilai false maka hashCode untuk kedua object akan mengembalikan nilai integer yang berbeda.
Kalau dua buah object dioperasikan dengan method equals mengembalikan nilai false maka hashCode kedua object tidak harus mengembalikan nilai interger yang berbeda, sama pun tidak masalah.

method hashCode akan digenerate dengan sendirinya oleh IDE seperti netbeans, eclipse, dll

public class Customer{
            private Long id;
            public void setId(Long aId){
                      this.id = aId;
           }
           public Long getId(){
                        return id;
           }
           public boolean equals(Object obj){
                      if(obj == null){
                               return false;
                      }
                      if(getClass() != obj.getClass()){
                               return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                               return false;
                     }

           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }

}

HashCode sangat vital ketika menggunakan collection yang memanfaatkan nilai hashCode, seperti HashSet HashMap. Perhitungan hashCode yang salah akan mengakibatkan kedua jenis collection ini berantakan.