-
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