Generic Collection 1.1 By pradeep (Must read)

download Generic Collection 1.1 By pradeep (Must read)

of 17

Transcript of Generic Collection 1.1 By pradeep (Must read)

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    1/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 1

    Chapter 7

    Collections and Generics

    ArrayList

    Array list can be polymorphically instantiated like thisList myList = new ArrayList();List myList = new ArrayList();

    You dont need to specify size of he ArrayList, because it growsdynamically.

    Auto-boxing plays an important role in collections. For exampleList myInts = new ArrayList();

    myInts.add(new Integer(42)); -- Prior java 5

    myInts.add(42); // Java 5, Autoboxing wraps the primitive to

    wrapper object

    ArrayList doesnt give anything to sort its contents. We sort an ArrayList using Collections class.

    We use Collections.sort() method to sort the elements of ArrayList. TheAPI definition of the method is

    public static

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    2/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 2

    By using the comparable interface we are stuck with only one sortingscheme.

    What if want multiple ways to sort our list, the answer is to useComparator interface.

    If we look at the Java API, the overloaded version of the sort() methodin java docs is given below

    public static void sort(List list,Comparator

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    3/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 3

    It is overloaded zillion of times for different primitives as well. Methods that sort primitives are based on natural order. An exam question can come, which will try to sort an array of

    primitives using a Comparator.

    Sort() methods for both collection classes Collections and Arrays arestatic methods and they alter the object they are sorting instead of

    returning a different sorted object.

    Whenever we sort an array or collection, always remember the elementsinside much be mutually comparable.

    Searching Arrays and Collections

    Searching arrays or collections has following rules

    Searches are performed using binarySearch method Successful searches return the int index of the element being searched. Unsuccessful searches return an int that respresents the insertion

    point.

    binarySearch() method uses negative numbers to indicate insertionpoints.

    Collection/Array being searched must be sorted first. If trying to search a collection, which is not sorted, then return

    results are unpredictable.

    If collection/array was sorted by natural order, then it must besearched by natural order, not by sending a comparator.

    If collection/array was sorted using a comparator, then it must besearched using a comparator only.

    Comparators cannot be used for searching Array of primitives.If search found = index is 0 based

    If not found = insertion point is based on 1

    Exam Gotchas For Searching And Sorting

    Searching an array or collection that has not been sorted. Using a comparator in either the sort or search but not both.

    Converting Arrays to Lists and List to Arrays

    List and Set classes have toArray() methods and Arrays class hasasList() method.

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    4/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 4

    Arrays.asList() method copies an array to a List. When asList() is used, array and List become joined by Hip and updating

    anyone of the following will cause the other data-structure to be

    updated as well.

    toArray() method comes into two forms. One return a brand new Object Array and other uses the array you sent

    as an argument as the destination array.

    toArray

    Object[] toArray()

    Returns an array containing all of the elements in this collection. If

    this collection makes any guarantees as to what order its elements are

    returned by its iterator, this method must return the elements in the

    same order.

    The returned array will be "safe" in that no references to it aremaintained by this collection. (In other words, this method must

    allocate a new array even if this collection is backed by an array).

    The caller is thus free to modify the returned array.

    This method acts as bridge between array-based and collection-based

    APIs.

    toArray T[] toArray(T[] a)

    Returns an array containing all of the elements in this collection; the

    runtime type of the returned array is that of the specified array. If

    the collection fits in the specified array, it is returned therein.Otherwise, a new array is allocated with the runtime type of the

    specified array and the size of this collection.

    If this collection fits in the specified array with room to spare

    (i.e., the array has more elements than this collection), the element

    in the array immediately following the end of the collection is set

    to null. (This is useful in determining the length of this

    collection onlyif the caller knows that this collection does not

    contain any null elements.)

    If this collection makes any guarantees as to what order its elements

    are returned by its iterator, this method must return the elements in

    the same order.

    Like thetoArray() method, this method acts as bridge between array-

    based and collection-based APIs. Further, this method allows precise

    control over the runtime type of the output array, and may, under

    certain circumstances, be used to save allocation costs.

    http://java.sun.com/javase/6/docs/api/java/lang/Object.htmlhttp://java.sun.com/javase/6/docs/api/java/lang/Object.htmlhttp://java.sun.com/javase/6/docs/api/java/util/Collection.html#toArray()http://java.sun.com/javase/6/docs/api/java/util/Collection.html#toArray()http://java.sun.com/javase/6/docs/api/java/util/Collection.html#toArray()http://java.sun.com/javase/6/docs/api/java/lang/Object.html
  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    5/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 5

    Suppose x is a collection known to contain only strings. The following

    code can be used to dump the collection into a newly allocated array

    of String:

    String[] y = x.toArray(new String[0]);

    Note that toArray(new Object[0]) is identical in function to toArray().

    Parameters:

    a - the array into which the elements of this collection are to be

    stored, if it is big enough; otherwise, a new array of the same runtime

    type is allocated for this purpose.

    Returns:

    an array containing all of the elements in this collection

    Throws:

    ArrayStoreException - if the runtime type of the specified array is not

    a supertype of the runtime type of every element in this collection

    NullPointerException - if the specified array is null

    Using Lists

    Lists keep things in order actually insertion order. LinkedList can be used to create a first-in, first-out queue. Duplicates might occur. Prior java-5, most common way to see elements of the list was by use of

    the iterator.

    Iterator is an object associated with a specific collection. Boolean hasNext() and Object next() from iterators are on the exam. hasNext() returns true if there is atleast one more item in the

    collection.

    Object next() returns next object in the collection and moves youforward to the element after the element just returned.

    List is an interface

    Using Sets

    Sets dont allow any duplicates. You can use TreeSet also, as it is sorted, but be careful while using

    TreeSet.

    HashSet doesnt guarantee any ordering. In TreeSet if you any add any object, always remember that objects

    should be mutually comparable because it is a sorted data structure. If

    http://java.sun.com/javase/6/docs/api/java/lang/ArrayStoreException.htmlhttp://java.sun.com/javase/6/docs/api/java/lang/NullPointerException.htmlhttp://java.sun.com/javase/6/docs/api/java/lang/NullPointerException.htmlhttp://java.sun.com/javase/6/docs/api/java/lang/ArrayStoreException.html
  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    6/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 6

    elements are not mutually comparable then at the run-time it will raise

    a ClassCastException.

    Generics

    Arrays are type-safe. Prior J-5, collections were not type safe. Non-generic collection can contain any kind of object but not a

    primitive.

    Since collection could have hold any type of object, the return typesused to be java.lang.Object

    Always a cast was required when a get() operation was performed. Generics takes care of both ends.

    List myList = new ArrayList();

    myList.add(Prithvi);

    myList.add(42) //compile time error as list is string

    Type in angular brackets is called the parametrized type or typeparameter.

    Type parameter for method argument can be written asPublic void testMe(List myList)

    Return can be declared type safe as wellpublic List testMe(List myList)

    Hetrogenous collections are almost identical to something like thisList myList = new ArrayLis();

    List myList = new ArrayList();

    //can hold any kind of object

    But pre-java5 generics and List are not identically same, butat times the differences really dont matter.

    Tricky issues are involved around polymorphism, method arguments andintegrating generic and non-generic code as we are concerned with

    Generics.

    Generics and Legacy Code

    The easiest issue is updating pre-java 5 to become compatible with java5 code of generics. Just add the type parameter in your declarations or

    where-ever necessary.

    Mixing Generic and Non-Generic Collections

    For example, we have something like thisList myList = new ArrayList();

    Test t = new Test();

    t.add(myList);

    Class Test{

    Public void add(List arrayList){arrayList.add(new String(42));

    }

    }

    Above example is completely valid for mixing generic and non-genericcode.

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    7/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 7

    Even above addition of a String into a list of type integer will beallowed.

    You will be only dead when you try to take the stuff out of the listand cast that String to an Integer.

    Main question arises, why such a situation is allowed? If generics arecompile time safe, then why not run-time?

    Such method when called will be compiled with warnings and if you wantto see a detailed explanation use the following command

    javac Xlink:unchecked Test.java

    The above command will generate all the warnings. Question still comes that why the above kind of code compiled? It is because the type information doesnt exist at run-time. All the generics code is strictly for the compiler. There is a process called type-erasure. The compiler after performing

    all the verification on your generics code, strips off the type

    information out of the byte-code.

    At run-time all legacy code and new generics code look the same as notyping information exisits.

    Why this type-erasure? Simple reason is to support the legacy code. For non-generic collections always watch out for unboxing problems. Non-generic collection will always return a java.lang.Object Unboxing cant convert a plain old Object to a primitive, even if that

    object refers to a Integer or any other wrapper class.

    Unboxing only coverts from wrapper class references to the primitives.For example.

    List test = new ArrayList();

    test.add(42);

    int x = (Integer) test.get(0) // cast is necessary

    List test = new ArrayList ();

    test.add(42);int x = test.get(0) // cast is not necessary

    Compiler warnings doesnt mean compiler failures. Generics are strictly a compile time operations.

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    8/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 8

    Compile time protection makes sure that you wont put any wrong thingand while taking the things out you dont a cast as well.

    We dont need run-time protection till we dont mix generics and thelegacy code.

    When you are using legacy code make sure we take care of unboxingproblems.

    Legacy code get() method will always return a type of Object and Objectcant be converted into a primitive even if the object refers to

    Integer object on heap. Unboxing converts only from a wrapper class

    reference.

    List myList = new ArrayList();

    myList.add(10);

    int value = (Integer) myList.get(0);

    Original regurn type is Object so must cast to Integer. Putting it in

    this way

    int value = myList.get(0);

    Above statement will produce compile time error.

    Watch out for missing casts related to java5 and pre-java 5

    Polymorphism And Generics

    Generics provide us with type safety but things become tricky when westart dealing with Polymorphishm.

    List

    List is called the Base type of collection

    Animal variable or Generic Typing

    //compiles fine

    List myList = new ArrayList();

    //compile time error

    List myList = new ArrayList();

    Rule type of variable must match the type of object. Just keep the generic type of reference equal to generic type of

    object.

    Polymorphism here only applies to base type which is called type ofcollection itself.

    Consider for example Array assignments for a moment//compiles fine

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    9/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 9

    Animal[] animalArray = new Animal[3];

    Animal[] myArray = new Dog[3];

    Object[] objectArray = new JButton[3];

    //generics way

    //does not compile

    List myList = new ArrayList();

    Just remember that polymorphism doesnt work the same way as it workswith arrays.

    Generics Method

    Consider something like thisClass Animal{

    public void eat(){

    System.out.println(In Animal);

    }

    }

    Class Dog extends Animal{

    public void eat(){

    System.out.println(In Dog);

    }

    }

    Class Bird extends Animal{

    public void eat(){

    System.out.println(In Bird);}

    }

    Public class AnimalTest{

    public void testEat(Animal[] animal){

    }

    Public static void main(String[] args){

    Animal[] animal = new Animal[3];

    Dog[] dog = new Dog[3];

    //pass either dog or Animal will work finenew AnimalTest().testEat(dog);

    }

    }

    When you apply same rules to Generics it wont work. Obviously method signatures declared with something like List

    will only accept only list of type Animal not something like List.

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    10/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 10

    For example, if we change testEat() method somewhat like thisPublic void testEat(List

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    11/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 11

    In the above scenario Arrays/Collections differ. You must be thinking, why it is dangerous for Collections and not for

    Arrays.

    Simple reason JVM behaves differently for Arrays and different forCollections.

    Lets walk through a couple of scenariospublic void testEat() {

    Dog[] dogs = {new Dog(), new Dog()};

    addAnimal(dogs); // no problem, send the Dog[] to the method

    }

    public void addAnimal(Animal[] animals) {

    animals[0] = new Dog(); // ok, any Animal subtype works

    }

    public void foo() {Cat[] cats = {new Cat(), new Cat()};

    addAnimal(cats); // no problem, send the Cat[] to the method

    }

    public void addAnimal(Animal[] animals) {

    //Problem, array passed way Cat and we added a Dog

    animals[0] = new Dog();

    }

    This scenario needs to be prevented in case of Array or ArrayList withone difference for arrays, compiler will allow you to get away but not

    for Collections.

    Reason is why you cant pass a List to List. Simple reasonis that, as reference type is of animal so you can add anything to the

    List and compiler have no way to stop you for adding things to the

    list.

    Main question, why compiler is allowing such a situation for Arrays andnot for Collections?

    Arrays have a RuntimeException called as ArrayStoreException which willbe thrown if you put anything wrong into the array at run-time.

    No such exception exists in case of Collections due to type-erasure.Means that, at run-time JVM knows the type of Arrays but not type of

    Collections as Arrays provide both compile and run-time safety.

    Remember this golden rule in case of genericsGeneric type of Object = generic type declared on reference

    Okay there is a method, which will make sure that you can use theList polymorphically and will also ensure that collection is

    use as read-only. It means that you cannot add anything into the

    collection.

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    12/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 12

    The way is by using the (?) wild-card approach. Method signatures with wild-cards will be changed like this

    //used without wild-card

    public void test(List myList)

    //used with wild-card

    public void test(List

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    13/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 13

    Above method you can pass a list of type Object as well. It is becauseObject class is the super-class of every class in Java.

    Super keyword is a wild card notation, that lets you add into thecollection in a safe but restricted way.

    Okay, now lets consider these two method signatures. Are they same?1- public void foo(List list) { }

    2- public void foo(List list) { }

    No, first signature means that you can pass anything to the method andsecond signature means that it can only accept lists of type Object.

    Remember that you can pass any kind of list in case of method 1 but youcannot add anything to the Collection.

    In second method, you can pass a list only of type Object and you canalso add to the list as compiler makes sure that only list of type

    Object will be passed to the method.

    Now if we have something like thisList

    Those two declarations are almost identical. Wild-cards can only be used with reference declarations, they cant be

    used as a type parameter when you are creating a certain Collection.

    Why?

    It is because reference types can be polymorphic but the object createdmust be of some specific type.

    Some examples are given below1) List list = new ArrayList();

    2) List

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    14/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 14

    For question one, that how we can know a particular class is expecting

    a parameterized type?

    API tells when a parameterized type is expected. Consider List interface example

    public interface List

    Above List is acting as a generic template. When writing code, we can change it from some generic type to specific

    type.

    public interface List = public interface List

    (Generic Type) (Specific Type)

    E is just symbolic, we can use any other valid Java identifier in itsplace.

    E = Element and is used when a template is a collection. T = stands for type and is used for things that are not collections. Lets come to the method level

    Public add(E object)

    When we are writing code, what-ever is the list type we are creating wecan replace E by that. For example

    public add(E object)

    List myList = new ArrayList();

    Human = Specific type of List so replace E with it

    public add(Human object)

    Some of the examples are presented below which will describe howgeneric typing can be used with classes in different ways.

    public class TestGenerics { // as the class type

    // as an instance variable type

    T anInstance;

    // as an array type

    T [] anArrayOfTs;

    // as an argument type

    TestGenerics(T anInstance) {

    this.anInstance = anInstance;

    }

    // as a return type

    T getT() {

    return anInstance;

    }

    }

    More than one parameterized type can be used for classes. For example

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    15/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 15

    public class UseTwo {

    T one;

    X two;

    UseTwo(T one, X two) {

    this.one = one;

    this.two = two;

    }

    T getT() { return one; }

    X getX() { return two; }

    // test it by creating it with

    public static void main (String[] args) {

    UseTwo twos = new UseTwo("foo", 42);

    String theT = twos.getT(); // returns a String

    int theX = twos.getX(); // returns Integer, unboxes to int

    }

    }

    We can specify a range of parameterized types also while creating aclass. These are called range bounds and are achieved through ? wild

    card notation. For example

    public class AnimalHolder{}

    AnimalHolder animal = new AnimalHolder();

    //Wont compile as Integer doesnt extend Animal

    AnimalHolder animal = new AnimalHolder();

    Notice that T is of Type

    Creating Generic Methods

    We can use parameter types at more granular level as for example methods. Inthis case, we dont need to declare the complete class as generic.

    //Describes the syntax of Generic Method

    public void makeArrayList(T t) {

    List list = new ArrayList();

    list.add(t);

    }

    a) Passing a generic Type Tb) Making an ArrayList based on the type being passed.c) Adding that type to the list.//More specific way when we want to invoke the makeArrayList methodpublic void makeArrayList(Dog t) {

    List list = new ArrayList();

    list.add(t);

    }

    a) Creating an ArrayList of Dogb) Adding Dog to the list

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    16/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 16

    One wild thing to note is the method signature of makeArrayList method.public void makeArrayList(T t) {

    }

    is placed before the return type of the method. So in case ofgeneric methods, you must declare the type before you use it.

    It is because the class itself is not generic only the method isgeneric.

    We can also range for the on generic methods as we did in case ofclasses. For example

    public void makeArrayList(T t)

    Method argument is NOT where we declared the type parameter T. If weneed to use type variable t, we must declare it either as class

    parameter type or in a method before return type. For example

    public void makeList(T t) { }

    The above statement can only be correct if there is actually a classednamed T.

    Can we declare constructor arguments as generic type also? For example//It is a legal constructor

    public Animal(T t){

    }

    We can declare a class with the name that is same as the type parameterplaceholder

    Class X{

    Public X(X x) {

    }

    }

    In above example X that is the constructor has no relation with typeparameter X. The compiler can parse it successfully.

    There is no naming conflict between class names, type parametersplaceholders and variable identifiers.

    One mistake and gotcha to remember, while creating generic classes ormethods is to use a in wildcard syntax. Such kind of syntax should

    be applied on place holder E or type T. For example

    //Wont compile. It is using wild card syntax not on T or E

    public class Human

  • 8/8/2019 Generic Collection 1.1 By pradeep (Must read)

    17/17

    April 24,

    2010GENERICS AND COLLECTIONS

    Prithvi Sehgal/Beenish Zaidi 17

    Question mark works when declaring a reference for a variable, it doesnot work for generic class and method declarations. For example

    //It wont compile based on the point above

    public class NumberHolder { ? aNum; }

    But if you replace the with a legal identifier

    public class NumberHolder { T aNum; } // Yes