Monday, October 27, 2008

Generics -Intermediary

Using Generic code with different Collection types

Lists

The usage with List Collections is quite straightforward as most of the java developers are familier with its API & its methods. Example of a code involving List interface is as follows:




List myList=new ArrayList();

MyObject a=new MyObject();

myList.add(a);

...

...




//Use this code to iterate

Iterator iterator=myList.Iterator();

while(iterator.hasNext()){

MyObject temp=iterator.next();

System.out.print(""+temp.toString());

}

//Or use the foll code

for(MyObject ss:myList){

MyObject temp=iterator.next();

System.out.print(""+temp.toString());

}

..

...

Sets

Set s=new HashSet();

System.out.println("Added an element"+s.add(new MyObject()));

s.add(new MyObject());

....




for(MyObject st:s)

System.out.println(st.toString());




Using TreeSets

Set mytreeSet=new TreeSet();




Now, class Power must be comparable, i.e. You can compare its elements .Eg. You can compare 1 & 2, "A" & "B", but how will you compare boy("Sumit") & boy("Rahul") ?

In order to do this, use java.util.Comparator interface.




Class Power implements Comparable{

public int FactorValue;

public int OtherValue;

.... other code including constructors

.

..

public int compareTo(Power t){ //Overriding the method through programmer implementation

if(this.FactorValue==t.FactorValue)

return 0;

if(this.FactorValue
return -1;

if(this.FactorValue>t.FactorValue)

return 1;

else

return 0;//Maybe throw an Assertion Error or an exception

}

//OR, You Could Also Use The Following Override


public int compareTo(Power t){ //Overriding through delegation

return(this.FactorValue.compareTo(t.FactorValue()));

/*

Works because Comparison is delegated to the int variable FactorValue in our class;

*/

}

}




If you wish to sort your object in a different manner, then use a Comparator. You can use it to sort even those class that you cannot modify. In such a case, create a (3rd Party) class like:




class OtherSort implements Comparator{

public int compare(MyObjectme,MyObject you){

return(me.OtherValue.compareTo(you.OtherValue));

}

}

Maps

Any class you use in a Map must implement the hashCode() and equals() methods. If you don't do so, then no compile/run time errors will occur, the code will just would'nt function the way it was supposed to.

Usage:

Map myMap=new HashMap();

Type1=Type Of KEY

Type2=Type Of VALUE

eg. Map shopList=new HashMap();




class Human{

String name;

Human(String s){

name=s;

}

public boolean equals(Object o){

if((o instanceof Human)&& ((Human)o).name==name)

return true;

else

return false;

}

public int hashCode(){ //More unique the hashCode returns a value,

return 5; //More efficient your class will be in retrieveing tho object from Map

}

public static void main(String[] args){

Map map=new HashMap();

map.put("we",new Human("Sumit"));

...

...

Human us;

us=map.get("we");

System.out.print(""+us.name);

}

}

Also, this is a valid code segment

Map> allWineLists=new LinkedHashMap>();

PriorityQueue

Queue queue=new PriorityQueue();

int[] values={1,6,3,8,34,55};

for(int i:values)

queue.offer(i); //Populate

System.out.println(""+queue.peek());//Print highest priority int

System.out.println(""+queue.size());

for(int i:values)

System.out.print(""+queue.poll(i));//Print and remove




A case where Mixing of Generic & non Generic collection creates Havoc




class Old{ //Old, Pre-Generic code

void InsertInt(List lst){

lst.add(new Integer(42));

}

}

class New{ //Newer class, under study

void go(){

List l=new ArrayList();

Old oldobject=new Old();

oldobject.InsertInt(l); //Adds Integer in an ArrayList OK!

}

void nogo(){

List l=new ArrayList();

Old oldobject=new Old();

oldobject.InsertInt(l); //Adds Integer in an ArrayList OOPS!, RuntimeException

}

}

This is primary reason why the compiler 'unhappily' chunks out an -Xlint:unchecked warning on compilation.




Polymorphism in Generics- Not Allowed

Hence you can't use

List mylist=new ArrayList();

Think again, the new ArrayList(); part can be changed by any other object of a class that is-a (instanceof) List implementer, but Generics is STRICTLY a COMIPILE-TIME mechanism, so no polymorphism applies.

A workaround of this problem is that Java allows you to add any subtype of the Type parameter.

Eg:

class Human{}

class Man extends Human{}

class Boy extends Human{}




List l=new ArrayList();

l.add(new Man()); //Allowed

l.add(new Boy()); //Allowed




Using Generic Methods

The above problem applies here also.Consider the following class hierachy.


Suppose, we have the following method,

public void addanAnimal(List an){

an.add(new Humans()); //legal

..

..

}

Now, if you invoke this method as:

List zoo=new ArrayList();

zoo.add(new Humans());

zoo.add(new Humans());

addanAnimal(zoo); //OK, as zoo's type is




but, List monkey=new ArrayList();

monkey.add(new Chimps());

..

..

addanAnimal(monkey);//ERROR,as monkey's type is not

This gives the following error on compilation.

addanAnimal(java.util.List) in "Classname"

cannot be applied to (java.util.List)

addanAnimal(monkey);

^

To avoid such kind of trouble, use a wildcard type parameter in the argument type. It is the programmer's assurance that the method will not ADD/Insert anything to the collection.

So, the method becomes: public void addanAnimal(List an)

This means, any collection can be assigned that is of type Animals or anything lower in its hierachy.

Note:

If you did'nt change the add(); statement, you'll get an error:=

"classname" : cannot find symbol

symbol : method add(Humans)

location : interface java.util.List

an.add(new Humans());

^

2. You can't use , even here, you'll have to make up with extends

3. ADDING IS ALLOWED with wildcard if it uses the super clause i.e. This means, you can add Humans,Animals,Objects in your collections, but not a Man (see object hierachy).

4. List is different from List

= Do not add anything, can be invoked with any type parameter

= Can add, but can be invoked only using Object type parameter

5. is the same as



No comments: