Sunday, 26 October 2008

Composite Pattern in Java

Composite allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Whenever we have a requirement of handling all the objects in the same structure we can go for composite pattern, where we can create a tree structure that contain both composition of objects and individual objects as nodes and treat all of them uniformly by using same operations.

A Composite contains components i.e.(composites(again can contain components) and leaf elements(cannot contain components again)).

Base Component defines an interface for all objects in the composition. The Client uses this base component class to deal with the objects in the composition. It may also provide the default behaviour for adding,removing or accessing child components. But mostly Component is an interface.

Composite: Defines beahviour of components having children and stores the child components. We can add and remove Component instances to this composite dynamically.

Leaf : Defines the behaviour for the elements in the composition. It doesn't have references to other Components

First we need to have a Component Interface.(BaseComponent where even you can give some default implementation also)


//Component
public interface Component {
public void add(Component countryComponent);
public void remove(Component countryComponent);
public Component getChild(int i);
public String getName();
public String getDescription();
public void print();
}


Then we have Leaf implementation, which further does'nt have references to other components.


//Leaf
public class Leaf implements Component{
private String name;
private String description;

public Leaf(String name,String description){
this.name = name;
this.description = description;
}

/* these three methods doesn't make
* sense for Leaf. So we can even make
* the Base Component as abstract Class
* and provide the default implementation
* instead of this approach.
*/


public void add(Component state){
System.out.println("Sorry, leaf can't have components ");
}

public void remove(Component state){
System.out.println("Sorry, leaf can't have components ");
}

public Component getChild(int i){
System.out.println("Sorry, leaf can't have components ");
throw new UnsupportedOperationException();
}

public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}


}


and finally the Composite Implementation which again can contain child components.


// Composite
public class Composite implements Component{
private String name;
private String description;

// list of State Components
List<Component> components = new ArrayList<Component>();

public Composite(String name, String description){
this.name = name;
this.description = description;
}

public void add(Component state){
components.add(state);
}

public void remove(Component state){
components.remove(state);
}

public Component getChild(int i){
return components.get(i);
}
public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
Iterator<Component> iterator = components.iterator();
while(iterator.hasNext()){
Component component = iterator.next();
component.print();
}
}

public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}


}




public class Test {
public static void main(String[] args) {
Component leaf = new Leaf("leaf","No components futher");
Component composite = new Composite("composite","Again has components");
Component subcomposite = new Composite("subcomposite","Sub Composite again contain components");

Component baseComponent = new Composite("BaseComponent","Includes all other components");

baseComponent.add(leaf);
baseComponent.add(composite);
baseComponent.add(subcomposite);

baseComponent.print();
}
}





A general consideration when implementing this pattern is whether each component should have a reference to its
container (composite). The benefit of such a reference is that it eases the traversal of the tree, but it also decreases your flexibility.

There are many tradeoffs in implementing Composite. You need to balance transperency and safety with your needs.

Hope this explanation helps.

References : Applied Java Patterns by Stephen Stelting and Olav Maassen

Head First Design Patterns

http://prashantjalasutram.blogspot.com/2007/11/composite-pattern-in-java.html

Friday, 17 October 2008

Associative Arrays in PL/SQL

Today I got a requirement to store values in name-value pair type arrays. Then I came to know about Associative Arrays in PL/SQL.

It was very useful. I would like to share with you the same.

Associative Arrays are particularly useful for name-value pair type arrays where you want to look up the value of a particular element without looping over the entire array.

It is like a simple version of a SQL table where you can retrieve values based on the primary key. As with any array in PL/SQL, they are most efficient when used with a small number of rows, such as simple lookup tables. If you find yourself loading tens of thousands of rows into an array, this might not suit you.

You can also use this when you want to generate some values dynamically just for look up, but dont want to store in database.

Not exactly but it gives the basic functionalities of Lists and Maps.

First Let us look at an example for name-value pairs:




declare
type nameArr is table of varchar2(20) index by NUMBER;
projectMembers nameArr;
begin
projectMembers('Sneha') := 6045;
projectMembers('Prashant') := 6046;
projectMembers('Pradeep') := 9879;
projectMembers('Praveen') := 9880;
projectMembers('Sheela') := 5645;
projectMembers('Shilpa') := 5646;

dbms_output.put_line(projectMembers('Sheela'));
dbms_output.put_line(projectMembers('Shilpa'));
end;
/

-- Results:
-- 5645
-- 5646



We can use the above strategy if we are handling less number of records. In this method we can directly get
the results without looping

But we can even use loop and define your own structure also like...



declare

-- Declare structure of record

TYPE address_rec_struct IS RECORD
(address_num NUMBER(2),
add_prefix VARCHAR(20),
org_name VARCHAR(20),
address VARCHAR(30));

-- Declare table datatype to hold an array of structure records

TYPE address_table IS TABLE OF address_rec_struct
INDEX BY BINARY_INTEGER;

-- Declare a table (t_add_table) with a type of address_table (an array of term /record structures)

t_add_table address_table;

l_index binary_integer;

begin


-- Delete each existing record in the table (say initialising)

FOR recs IN t_add_table.first .. t_add_table.last LOOP
t_add_table.Delete(recs);
END LOOP ;

-- index pointing to first record
l_index := t_add_table.first;

loop

-- add your functionality like
--dynamically adding values

t_add_table(l_index).address_num = 1;
t_add_table(l_index).add_prefix = 'trading as';
t_add_table(l_index).org_name = 'Spencers';
t_add_table(l_index).address = 'Metro Center, NewCastle.';


exit when l_index = t_add_table.last;
l_index := t_add_table.next(l_index);
end loop;
end;
/



further my requirement includes sorting of the assosiative arrays based on particular column.

For this we need to create one more table structure making the column you want to sort as an index.

Let us look at an example where I want to parse the address and pick out all the different addresses based on some keywords and their starting indexes in that string.


Our first approach is to have table structure with values which are unsorted.


--Declare Record type
TYPE r_split_address IS RECORD (keyphrase VARCHAR2(50),startindex BINARY_INTEGER);


-- Declare the table
TYPE t_split_address1 IS TABLE OF r_split_address
INDEX BY BINARY_INTEGER;


--declare my table variable
split_address1 t_split_address1;


-- Declare a temporary holding variable
v_current binary_integer;

BEGIN
-- Initialize the array in unsorted order
split_address1(1).keyphrase := 'residing at';
split_address1(1).startindex := 29;
split_address1(2).keyphrase := 'trading at';
split_address1(2).startindex := 10;
split_address1(3).keyphrase := 'formerly at';
split_address1(3).startindex := 34;


-- Retrieve the first index variable

v_current := split_address1.FIRST;
LOOP

-- Exit when we hit the bottom of the table
EXIT WHEN v_current IS NULL;

-- Print out the index variable
DBMS_OUTPUT.PUT_LINE('Index is: ' || v_current );

-- Print out the data values at the current index value
DBMS_OUTPUT.PUT_LINE('KeyPhrase is: ' || split_address1(v_current).keyphrase );
DBMS_OUTPUT.PUT_LINE('StartIndex is: ' || split_address1(v_current).startindex );

-- Get the next index variable
v_current := split_address1.NEXT(v_current);

END LOOP;


Output:
Index is: 1
KeyPhrase is: residing at
StartIndex is: 29

Index is: 2
KeyPhrase is: trading at
StartIndex is: 10

Index is: 1
KeyPhrase is: formerly at
StartIndex is: 34

---------------------------

Now I want to sort the data by startIndex

The only thing you need to do is declare another table structure of same record type and point the INDEX
to be startIndex.



--Declare Record type
TYPE r_split_address IS RECORD (keyphrase VARCHAR2(50),startindex BINARY_INTEGER);


-- Declare the table
TYPE t_split_address1 IS TABLE OF r_split_address
INDEX BY BINARY_INTEGER;


-- for the second table
TYPE t_split_address2 IS TABLE OF r_split_address
INDEX BY BINARY_INTEGER;


--declare my table variable
split_address1 t_split_address1;


split_address2 t_split_address2;


-- Declare a temporary holding variable
v_current binary_integer;


BEGIN

-- Initialize the array in unsorted order
split_address1(1).keyphrase := 'residing at';
split_address1(1).startindex := 29;

split_address1(2).keyphrase := 'trading at';
split_address1(2).startindex := 10;

split_address1(3).keyphrase := 'formerly at';
split_address1(3).startindex := 34;

-- Retrieve the first index variable

v_current := split_address1.FIRST;

LOOP

-- Exit when we hit the bottom of the table
EXIT WHEN v_current IS NULL;

-- Print out the index variable
DBMS_OUTPUT.PUT_LINE('Index is: ' || v_current );

-- Print out the data value at the current index value

DBMS_OUTPUT.PUT_LINE('KeyPhrase is: ' || split_address1(v_current).keyphrase );

DBMS_OUTPUT.PUT_LINE('StartIndex is: ' || split_address1(v_current).startindex );

-- Get the next index variable
v_current := split_address1.NEXT(v_current);

END LOOP;

-- Display each value directly by using the key
DBMS_OUTPUT.PUT_LINE('Key is: 1 Value is: ' || split_address1(3).keyphrase );
DBMS_OUTPUT.PUT_LINE('Key is: 2 Value is: ' || split_address1(3).startindex );


----***Sorting ***-----

v_current := split_address1.FIRST;

LOOP

EXIT WHEN v_current IS NULL;

-- pointing the INDEX to the startIndex column of the first table

split_address2(split_address1

(
v_current).startindex) := split_address1(v_current);

v_current := split_address1.NEXT(v_current);

END LOOP;


---- ***To display the sorted elements***----

v_current := split_address2.FIRST;

LOOP

EXIT WHEN v_current IS NULL;

DBMS_OUTPUT.PUT_LINE('Index is: ' || v_current ||' and KeyPhrase1 is: ' || split_address2(v_current).keyphrase);

v_current := split_address2.NEXT(v_current);

END LOOP;


Output:

Index is: 10 and KeyPhrase is: trading at

Index is: 29 and KeyPhrase is: residing at

Index is: 34 and KeyPhrase is: formerly at





Hope it will be useful...

Thursday, 2 October 2008

State Design Pattern

The State Pattern allows an object to alter its behaviour when its internal state changes. The object will appear to change its class

What does it mean for an object to "appear to change its class?" Think about it from the perspective of a client: if an object you are using can completely change its behaviour, then it appears to you that the object is actually instantiated from another class. In reality, however you know that we are using composition to give the appearance of a class change by simply referencing different state objects.

By encapsulating each state into a class, we localize any changes that will need to be made.

State transitions can be controlled by State Classes or by Context Classes.



Objects are often discussed in terms of having a "state" that describes their exact conditions in a given time, based upon the values of their properties. The particular values of the properties affect the object's behavior.

For example the behaviour of an object Room's isDark() is different when the values of property light changes.

public boolean isDark()
{
if(swichLight().equalsIgnoreCase("off"))
return true;
else
return false;
}


Let us look at detailed example

//With out using StateDesign Pattern



public class Life
{
final static int CHILD = 0;
final static int BOY = 1;
final static int YOUTH = 2;
final static int OLD = 3;

int state = CHILD;

public void children(){
if(state == CHILD){
System.out.println("Go and Play...");
state = BOY;
}
else if(state == BOY)
System.out.println("Don't behave like a kid");
else if(state == YOUTH)
System.out.println("Don't behave like a kid");
else if(state == OLD)
System.out.println("Don't behave like a kid");
}

public void schoolBoy(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY){
System.out.println("Its time to go to school");
state = YOUTH;
}
else if(state == YOUTH)
System.out.println("Don't behave like a boy");
else if(state == OLD)
System.out.println("Don't behave like a boy");
}

public void youngGeneration(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY)
System.out.println("grow up...");
else if(state == YOUTH){
System.out.println("Right time to achieve my goals...");
state = OLD;
}
else if(state == OLD)
System.out.println("You are no longer youth");
}

public void oldGeneration(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY)
System.out.println("grow up...");
else if(state == YOUTH){
System.out.println("grow up...");
state = OLD;
}
else if(state == OLD)
System.out.println("I can guide you all");
}

public String toString(){
return state+"";
}

// Other methods...
}



But if we use State Design Pattern here, we can get rid of this messy if else code in Life Class and also make it flexible.

//With State Design Pattern


public interface State{
public void childhood();
public void boyhood();
public void youth();
public void old();
}



public class ChildHoodState implements State{

Life life;

public ChildHoodState(Life life){
this.life = life;
}

public void childhood(){
System.out.println("Go and Play...");
life.setState(life.boyHoodState);
}
public void boyhood(){
System.out.println("Don't behave like a kid");
}
public void youth(){
System.out.println("Don't behave like a kid");
}
public void old(){
System.out.println("Don't behave like a kid");
}
}



public class BoyHoodState implements State{

Life life;

public BoyHoodState(Life life){
this.life = life;
}

public void childhood(){
System.out.println("Grow up.. ");
}
public void boyhood(){
System.out.println("Its time to go to school");
life.setState(life.youthState);
}
public void youth(){
System.out.println("Don't behave like a boy");
}
public void old(){
System.out.println("Don't behave like a boy");
}
}



public class YouthState implements State{

Life life;

public YouthState(Life life){
this.life = life;
}

public void childhood(){
System.out.println("Grow up...");
}
public void boyhood(){
System.out.println("Grow up...");
}
public void youth(){
System.out.println("Right time to achieve my goals...");
life.setState(life.oldState);
}
public void old(){
System.out.println("You are no longer youth");
}
}



public class OldState implements State{

Life life;

public OldState(Life life){
this.life = life;
}

public void childhood(){
System.out.println("Grow up...");
}
public void boyhood(){
System.out.println("Grow up...");
}
public void youth(){
System.out.println("Grow up...");
}
public void old(){
System.out.println("I can guide you all");
}
}



public class Life{
// All the States
State childHoodState;
State boyHoodState;
State youthState;
State oldState;

// initialise them
State state = childHoodState;

public Life(){
childHoodState = new ChildHoodState(this);
boyHoodState = new BoyHoodState(this);
youthState = new YouthState(this);
oldState = new OldState(this);
}

// Delegate to current state

public void children(){
state.childhood();
}

public void schoolBoy(){
state.boyhood();
}

public void youngGeneration(){
state.youth();
}

public void oldGeneration(){
state.old();
}

// for transition of state
public void setState(State state){
this.state = state;
}

// Many other methods needed... including getters and setters of each State

}



public class TestLife{
public static void main(String[] args) {
Life life = new Life();
System.out.println(life);

life.children();
life.schoolBoy();
life.youngGeneration();
life.oldGeneration();

System.out.println(life);


}
}



What we are doing here is implementing the behaviours that are appropriate for the state we are in. In some cases this behaviour includes moving the Life forward to new state.


We will have similar kind of classes for 'YouthState' and 'OldState' also ...


From the above explanation we came to know that State Design Pattern is a fully encapsulated, self-modifying Strategy Design Pattern.


Difference between Strategy and State Design Patterns.

1. State: Encapsulate interchangable behaviours and use delegation to decide which behaviour to use.

Strategy: Subclasses decide how to implement steps in an algorithm.


2. With State Pattern we have a set of behaviours encapsulated in state objects; at any time the context is delegating to one of those states. Over time, the current state changes across the set of state objecs to reflect the internal state of context, so the context's behaviour changes over time as well. The client usually knows very little, if anything about the state objects.

With Strategy, the client usually specifies the strategy object that the context is composed with. Now, while the pattern provides the flexibility to change the strategy object at runtime, often there is a strategy object that is most appropriate for a context object.

3. Think of the State Pattern as an alternative to putting lots of conditionals in your context; by encapsulating the behaviours within state objects, you can simply change the state object in context to change its behaviour.

In general think of strategy pattern as a flexible alternative to subclassing; if you use inheritence to define the behaviour of a subclass then you are stuck with that behaviour even if you need to change it. With Strategy you can change the behaviour by composing with a different object.


Disadvantage: By encapsulating state behaviour into seperate classes, you'll always end up with more classes in your design. That's often the price you pay for flexibility.


Hope this explanation helps...

Quick review of Collections in Java

Yesterday I again tried to go through SCJP Sun Certified Programmer for Java 5 Study Guide by Keithy Sierra and Bert Bates for the second time. Even its second time, I found it interesting again.

I would like to thank authors for producing such an excellent book.

I think all chapters are worth to read but I enjoyed reading Threads and Generics and Collections.

For a quick go round, I would like to share some of the important features In Java Collections I came to know from this book

The most frequently used core interfaces are

1. Collection
2. Set
3. SortedSet
4. List
5. Map
6. SortedMap
7. Queue

and the most frequently used core concrete implementation classes are

1. HashMap
2. HashSet
3. ArrayList
4. PriorityQueue
5. Collections
6. Hashtable
7. LinkedHashSet
8. Vector
9. Arrays
10. TreeMap
11. TreeSet
12. LinkedList
13. LinkedHashMap


Remember none of the Map-related classes and interfaces extend from Collection.

So while SortedMap, Hashtable, HashMap, TreeMap, and LinkedHashMap are all thought of as collections, none are actually extended from Collection(interface).

collection (lowercase c), which represents any of the data structures in which objects are stored and iterated over.

Collection (capital C), which is actually the java.util.Collection interface from which Set, List, and Queue extend. (That's right, extend, not implement. There are no direct implementations of Collection.)

Collections (capital C and ends with s) is the java.util.Collections class that holds a pile of static utility methods for use with collections.

Collections come in four basic flavors:

1. Lists of things Ordered, duplicates allowed, with an index.

2. Sets of things May or may not be ordered and/or sorted; duplicates not allowed.

3. Maps of things with keys May or may not be ordered and/or sorted; duplicate keys are not allowed.

4. Queues of things to process Ordered by FIFO or by priority.


But there are sub-flavors within those four flavors of collections:

Sorted
Unsorted
Ordered
Unordered

An implementation class can be unsorted and unordered, ordered but unsorted, or both ordered and sorted.

But an implementation can never be sorted but unordered, because sorting is a specific type of ordering.
For example, a HashSet is an unordered, unsorted set, while a LinkedHashSet is an ordered (but not sorted) set that maintains the order in which objects were inserted.

Ordered: When a collection is ordered, it means you can iterate through the collection in a specific (not-random) order.

Sorted: Order in the collection is determined according to some rule or rules, known as the sort order. A sort order has nothing to do with when an object was added to the collection, or when was the last time it was accessed, or what "position" it was added at. Sorting is done based on properties of the objects themselves. You put objects into the collection, and the collection will figure out what order to put them in, based on the sort order.

A collection that keeps an order (such as any List, which uses insertion order) is not really considered sorted unless it sorts using some kind of sort order.

Most commonly, the sort order used is something called the natural order.

List Interface:

A List cares about the index. (Ordered but Not Sorted)

The one thing that List has that non-lists don't have is a set of methods related to the index.

All three List implementations are ordered by index position—a position that you determine either by setting an object at a specific index or by adding it without specifying position, in which case the object is added to the end.

ArrayList: Fast iteration and fast random access.

ArrayList implements RandomAccess interface—a marker interface (meaning it has no methods) that says, "this list supports fast (generally constant time) random access."

Vector: It's like a slower ArrayList, but it has synchronized methods.

LinkedList: Elements are doubly-linked to one another. Good for adding/remove elements to the ends, i.e., stacks and queues.


Note :
--> Choose ArrayList over a LinkedList when you need fast iteration i.e random access.
--> Go for Linked List when you need fast insertion and deletion.


Set Interface : A Set cares about uniqueness—it doesn't allow duplicates.

HashSet: Fast access, assures no duplicates, provides no ordering.

LinkedHashSet: No duplicates; iterates by insertion order.

TreeSet: No duplicates; iterates in sorted order. Implements SortedSet.

Note : When using HashSet or LinkedHashSet, the objects you add to them must override hashCode(). If they don't override hashcode(), the default object. hashcode() method will allow multiple objects that you might consider "meaningfully equal" to be added to your "no duplicates allowed" set.

Map Interface : Cares about unique identifiers. Supports use of key/value or name/value pair. The Map implementations let you do things like search for a value based on the key, ask for a collection of just the values, or ask for a collection of just the keys.

Like Sets, Maps rely on the equals() method to determine whether two keys are the same or different.

HashMap: unsorted, unordered Map. Fastest updates (key/value pairs); allows one null key, many null values.

Hashtable : Like a slower HashMap (as with Vector, due to its synchronized methods). No null values or null keys allowed.

LinkedHashMap : Faster iterations; iterates by insertion order or last accessed; allows one null key, many null values.

TreeMap : A sorted map. Implements SortedMap.

Note:
LinkedList ---> faster insertions and deletions and slower iterations (compared to arraylist)
LinkedHashMap ---> faster iterations and slower insertions and deletions (compared to HashMap)

Queue Interface : Although other orders are possible, queues are typically thought of as FIFO (first-in, first-out). Queues support all of the standard Collection methods and they also add methods to add and subtract elements and review queue elements.

PriorityQueue: A to-do list ordered by the element's priority.


Sorting Collections

Comparable Interface : Used by the Collections.sort() method and the java.utils.Arrays.sort() method to sort Lists and arrays of objects, respectively.

To implement Comparable, a class must implement a single method, compareTo().

int x = thisObject.compareTo(anotherObject);

The compareTo() method returns an int with the following characteristics:

negative
If thisObject < anotherObject

zero
If thisObject == anotherObject

positive
If thisObject > anotherObject

The sort() method uses compareTo() to determine how the List or object array should be sorted.

Since you get to implement compareTo() for your own classes, you can use whatever weird criteria you prefer, to sort instances of your classes.

Let us look at an example of trying to sort employees by their name,



public class Employee implements Comparable<Employee> { // line 1

private String name;

Employee(String name) {
this.name = name;
}
public int compareTo(Employee employee) { //line 2
return name.compareTo(employee.getName());
}
public String toString() {
return name ;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


In line 1 we declare that class Employee implements Comparable in such a way that Employee objects can be compared to other Employee objects. In line 2 we implement compareTo() by comparing the two Employee object's names. Since we know that the names are Strings, and that String implements Comparable, this is an easy way to sort our Employee objects, by name.


class TestSort{
public static void main(String[] args) {
List<Employee> employees = new ArrayList<Employee>();

Employee employee1 = new Employee("Sneha");
Employee employee2 = new Employee("Prashant");

employees.add(employee1);
employees.add(employee2);

System.out.println("unsorted " + employees);

Collections.sort(employees);

System.out.println("sorted " + employees);
}
}




Note : We can't sort Employee collections in different ways in the above Example as we can only implement compareTo() once in a class.
-->So go with Comparator when you want to sort a given collection any number of different ways.


Note :
--> Remember that when you override equals() you MUST take an argument of type object,
--> But when you override compareTo() you should take an argument of the type you're sorting.


Sorting with Comparator

In Collections.sort() method you might have noticed that there is an overloaded version of sort() that takes a List, AND something called a Comparator.

The Comparator interface gives you the capability to sort a given collection any number of different ways.

The other handy thing about the Comparator interface is that you can use it to sort instances of any class—even classes you can't modify—unlike the Comparable interface, which forces you to change the class whose instances you want to sort.

The Comparator interface is also very easy to implement, having only one method, compare().

Now let us try to sort the Employees by their Birthdays using Comparator.



public class BirthdayComparator implements Comparator<Employee>{

private String sortByColumn = null;
private String sortBy = null;

public BirthdayComparator(String sortByColumn,String sortBy){
this.sortByColumn = sortByColumn;
this.sortBy = sortBy;
}

public int compare(Employee src,Employee dest){

if(sortByColumn.equalsIgnoreCase("dateOfBirth")){
if(sortBy.equalsIgnoreCase("asc"))
return src.getDateOfBirth().compareTo(dest.getDateOfBirth());
else
return dest.getDateOfBirth().compareTo(src.getDateOfBirth());
}

// sort by name
else{
if(sortBy.equalsIgnoreCase("asc"))
return src.getName().compareTo(dest.getName());
else
return dest.getName().compareTo(src.getName());
}
}
}

public class Employee {

private String name;
private Date dateOfBirth;

Employee(String name, Date dateOfBirth) {
this.name = name;
this.dateOfBirth = dateOfBirth;
}

public String toString() {
return name ;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}


class TestSort{
public static void main(String[] args) {
List<Employee> employees = new ArrayList<Employee>();

Calendar calendar1 = Calendar.getInstance();
calendar1.set(2008,2,12);

Date snehaDOB = calendar1.getTime();

Calendar calendar2 = Calendar.getInstance();
calendar2.set(2008,4,12);

Date prashantDOB = calendar2.getTime();

Employee employee1 = new Employee("Sneha",snehaDOB);
Employee employee2 = new Employee("Prashant",prashantDOB);

employees.add(employee1);
employees.add(employee2);

System.out.println("unsorted " + employees);

BirthdayComparator<Employee> birthdayComparator=new BirthdayComparator<Employee>("dateOfBirth","asc"):

Collections.sort(employees,birthdayComparator);

System.out.println("sorted " + employees);
}
}


Arrays.sort() method is overloaded about a million times to provide a couple of sort methods for every type of primitive.

The Arrays.sort() methods that sort primitives always sort based on natural order. Don't be trying to sort a primitive array using a Comparator.

Finally, remember that the sort() methods for both the Collections class and the Arrays class are static methods, and that they alter the objects they are sorting, instead of returning a different sorted object.

Note : Whenever you want to sort an array or a collection, the elements inside must all be mutually comparable.


Searching Arrays and Collections


The Collections class and the Arrays class both provide methods that allow you to search for a specific element. When searching through collections or arrays, the following rules apply:

Searches are performed using the binarySearch() method.

Successful searches return the int index of the element being searched.

Unsuccessful searches return an int index that represents the insertion point.

The insertion point is the place in the collection/array where the element would be inserted to keep the collection/array properly sorted.

As positive return values and 0 indicate successful searches, the binarysearch() method uses negative numbers to indicate insertion points.

Since 0 is a valid result for a successful search, the first available insertion point is -1. Therefore, the actual insertion point is represented as (-(insertion point) -1). For instance, if the insertion point of a search is at element 2, the actual insertion point returned will be -3.

Note :
--> The collection/array being searched must be sorted before you can search it.
--> If you attempt to search an array or collection that has not already been sorted, the results of the search will not be predictable.

If the collection/array you want to search was sorted in natural order, it must be searched in natural order. (This is accomplished by NOT sending a Comparator as an argument to the binarysearch() method.)

If the collection/array you want to search was sorted using a Comparator, it must be searched using the same Comparator, which is passed as the second argument to the binarysearch() method. Remember that Comparators cannot be used when searching arrays of primitives.


Converting Arrays to Lists to Arrays

There are a couple of methods that allow you to convert arrays to Lists, and Lists to arrays.

The List and Set classes have toArray() methods, and the Arrays class has a method called asList().

The Arrays.asList() method copies an array into a List. The API says, "Returns a fixed-size list backed by the specified array. (Changes to the returned list 'write through' to the array.)"

Note : When you use the asList() method, the array and the List become joined at the hip. When you update one of them, the other gets updated automatically. Let's take a look:


String [] sa = {"one", "two", "three", "four"};
List sList = Arrays.asList(sa); // make a List
System.out.println("size " + sList.size());
System.out.println("idx2 " + sList.get(2));

sList.set(3,"six"); // change List
sa[l] = "five"; // change array
for(String s : sa)
System.out.print(s + " ");
System.out.println("\nsl[1] " + sList.get(1));



This produces

size 4
idx2 three
one five three six
sl[1] five


In the PriorityQueue Class we have 3 methods that are important to understand

offer() (which is similar to add()),
peek() (which retrieves the element at the head of the queue, but doesn't delete it),
and poll() (which retrieves the head element and removes it from the queue).

Note : It's important to know some of the details of natural ordering. The following code from certification book will help you understand the relative positions of uppercase characters, lowercase characters, and spaces in a natural ordering:


String[] sa = {">ff<", "> f<", ">f <", ">FF<" }; // ordered?
PriorityQueue<String> pq3 = new PriorityQueue<String>();
for(String s : sa)
pq3.offer(s);
for(String s : sa)
System.out.print(pq3.poll() + " ");



This produces:

> f< >FF< >f < >ff<

If you remember that spaces sort before characters and that uppercase letters sort before lowercase characters, you should be good to go for the exam.


Last but not least let us look at overriding of hashCode() and equals() methods.

--> equals(), hashCode(), and toString() are public.

--> Use == to determine if two reference variables refer to the same object.

--> Use equals() to determine if two objects are meaningfully equivalent.

--> If you don't override equals(), your objects won't be useful hashing keys.

--> If you don't override equals(), different objects can't be considered equal as Object class uses ==
inside equals() method to check whether two objects are equal or not.

--> Strings and wrappers override equals() and make good hashing keys.

--> When overriding equals(), use the instanceof operator to be sure you're evaluating an appropriate class.

--> When overriding equals(), compare the objects' significant attributes.

--> Highlights of the equals() contract:
1. Reflexive: x.equals(x) is true.
2. Symmetric: If x.equals(y) is true, then y.equals(x) must be true.
3. Transitive: If x.equals(y) is true, and y.equals(z) is true, then z.equals(x) is true.
4. Consistent: Multiple calls to x.equals(y) will return the same result.
5. Null: If x is not null, then x.equals(null) is false.

--> If x.equals(y) is true, then x.hashCode() == y.hashCode() is true.

--> If you override equals(), override hashCode().

--> HashMap, HashSet, Hashtable, LinkedHashMap, & LinkedHashSet use hashing.

--> An appropriate hashCode() override sticks to the hashCode() contract.

--> An efficient hashCode() override distributes keys evenly across its buckets.

--> An overridden equals() must be at least as precise as its hashCode() mate.

--> To reiterate: if two objects are equal, their hashcodes must be equal.

--> It's legal for a hashCode() method to return the same value for all instances (although in practice it's very inefficient).

--> Highlights of the hashCode() contract:
1. Consistent: multiple calls to x.hashCode() return the same integer.
2. If x.equals(y) is true, x.hashCode () == y. hashCode() is true.
3. If x.equals(y) is false, then x.hashCode() == y.hashCode() can be either true or false, but false will tend to create better efficiency.

--> transient variables aren't appropriate for equals() and hashCode().


Hope it will be useful