Core Java - Collection


A Collection represents a single unit of objects, i.e., a group. Normally, collection is interface.

Collections :
The Collection in Java is a framework that provides an architecture to store and manipulate the group of objects.
Java Collections can achieve all the operations that you perform on a data such as searching, sorting, insertion, manipulation, and deletion.
Java Collection means a single unit of objects. Java Collection framework provides many interfaces (Set, List, Queue, Deque) and classes (ArrayList, Vector, LinkedList, PriorityQueue, HashSet, LinkedHashSet, TreeSet).

Framework :
It is a ready made architecture with pre-defined logics to perform operation with collection is called as framework.

Collection Framework :
The combination of set of classes and interfaces with predefined logics given in the form of methods is called as Collection Framework.

Hierarchy of Collection Framework :
Let us see the hierarchy of Collection framework. The java.util package contains all the classes and interfaces for the Collection framework.

collection

A collections framework is a unified architecture for representing and manipulating collections. All collections frameworks contain the following:

  • Interfaces : These are abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. In object-oriented languages, interfaces generally form a hierarchy.

  • Implementations, i.e., Classes : These are the concrete implementations of the collection interfaces. In essence, they are reusable data structures.

  • Algorithms : These are the methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. The algorithms are said to be polymorphic: that is, the same method can be used on many different implementations of the appropriate collection interface.


  • In addition to collections, the framework defines several map interfaces and classes. Maps store key/value pairs. Although maps are not collections in the proper use of the term, but they are fully integrated with collections.

    The Collection Interfaces :
    The collections framework defines several interfaces. This section provides an overview of each interface:
        S.No    Interfaces	                                      Description
       ----- --------------------    ----------------------------------------------------------------------------------------------
        1	 Collection Interface    This enables you to work with groups of objects, it is at the top of the collections hierarchy.
    
        2	 List Interface          This extends Collection and an instance of List stores an ordered collection of elements.
    
        3	 Set Interface	         This extends Collection to handle sets, which must contain unique elements.
    
        4	 SortedSet Interface	 This extends Set to handle sorted sets.
    
        5	 Map Interface	         This maps unique keys to values.
    
        6	 Map.Entry Interface     This describes an element (a key/value pair) in a map. This is an inner class of Map.
    
        7	 SortedMap Interface     This extends Map so that the keys are maintained in ascending order.
    
    
    The Collection Classes :
    Java provides a set of standard collection classes that implement Collection interfaces. Some of the classes provide full implementations that can be used as-is and others are abstract class, providing skeletal implementations that are used as starting points for creating concrete collections.

    The standard collection classes are summarized in the following table:
        S.No      Classes	                                   Description
       ------ --------------------    --------------------------------------------------------------------------
        1	  AbstractCollection	    Implements most of the Collection interface.
    
        2	  AbstractList	            Extends AbstractCollection and implements most of the List interface.
    
        3	  LinkedList	            Implements a linked list by extending AbstractSequentialList.
    
        4	  ArrayList                 Implements a dynamic array by extending AbstractList.
    
        5	  HashSet                   Extends AbstractSet for use with a hash table.
    
        6	  LinkedHashSet	            Extends HashSet to allow insertion-order iterations.
    
        7	  Treeset                   Implements a set stored in a tree. Extends AbstractSet.
    
        8	  HashMap                   Extends AbstractMap to use a hash table.
    
        9	  TreeMap                   Extends AbstractMap to use a tree.
    
        10	  LinkedHashMap	            Extends HashMap to allow insertion-order iterations.
    
    
    Collection Algorithms :
    The collections framework defines several algorithms that can be applied to collections and maps. These algorithms are defined as static methods within the Collections class.
    Several of the methods can throw a ClassCastException, which occurs when an attempt is made to compare incompatible types, or an UnsupportedOperationException, which occurs when an attempt is made to modify an unmodifiable collection.

    Collections define three static variables : EMPTY_SET, EMPTY_LIST, and EMPTY_MAP. All are immutable
        S.No	   Algorithms	                                Description
       ------ ----------------------------  ---------------------------------------------------------
        1	   The Collection Algorithms	    Here is a list of all the algorithm implementation.
    
    
    How to use an Iterator ?
    Often, you will want to cycle through the elements in a collection. For example, you might want to display each element.
    The easiest way to do this is to employ an iterator, which is an object that implements either the Iterator or the ListIterator interface.
    Iterator enables you to cycle through a collection, obtaining or removing elements. ListIterator extends Iterator to allow bidirectional traversal of a list and the modification of elements.
        S.No	 Iterator Methods	                                Description
       ------ -----------------------  ---------------------------------------------------------------------
        1	   Using Java Iterator	    Here is a list of all the methods with examples provided by Iterator 
                                        and ListIterator interfaces.		
    
    
    Using Java Iterator :
    Often, you will want to cycle through the elements in a collection. For example, you might want to display each element.
    The easiest way to do this is to employ an iterator, which is an object that implements either the Iterator or the ListIterator interface.
    Iterator enables you to cycle through a collection, obtaining or removing elements. ListIterator extends Iterator to allow bidirectional traversal of a list, and the modification of elements.
    Before you can access a collection through an iterator, you must obtain one. Each of the collection classes provides an iterator( ) method that returns an iterator to the start of the collection. By using this iterator object, you can access each element in the collection, one element at a time.

    In general, to use an iterator to cycle through the contents of a collection, follow these steps:
  • Obtain an iterator to the start of the collection by calling the collection's iterator( ) method.
  • Set up a loop that makes a call to hasNext( ). Have the loop iterate as long as hasNext( ) returns true.
  • Within the loop, obtain each element by calling next( ).

  • For collections that implement List, you can also obtain an iterator by calling ListIterator.

    Methods Declared by Iterator :
       S.No	    Methods	                                  Description
       ---- --------------------  ---------------------------------------------------------------------------------------
        1	   boolean hasNext( )   Returns true if there are more elements. Otherwise, returns false.
    
        2	   Object next( )       Returns the next element. Throws NoSuchElementException if there is not a next element.
    
        3	   void remove( )       Removes the current element. Throws IllegalStateException if an attempt is made to call 
                                    remove( ) that is not preceded by a call to next( ).
    
    
    Methods Declared by ListIterator :
        S.No	    Methods	                                    Description
       ------ --------------------    -------------------------------------------------------------------------------------
        1	  void add(Object obj)	  Inserts obj into the list in front of the element that will be returned by the next 
                                      call to next( ).
    
        2	  boolean hasNext( )	  Returns true if there is a next element. Otherwise, returns false.
    
        3	  boolean hasPrevious( )  Returns true if there is a previous element. Otherwise, returns false.
    
        4	  Object next( )          Returns the next element. A NoSuchElementException is thrown if there is not a next 
                                      element.
    
        5	  int nextIndex( )        Returns the index of the next element. If there is not.
    
        6	  Object previous( )	  Returns the previous element. A NoSuchElementException is thrown if there is not a 
                                      previous element.
    
        7	  int previousIndex( )	  Returns the index of the previous element. If there is not a previous element, returns -1.
    
        8	  void remove( )          Removes the current element from the list. An IllegalStateException is thrown if remove( )
                                      is called before next( ) or previous( ) is invoked.
    
        9	  void set(Object obj)	  Assigns obj to the current element. This is the element last returned by a call 
                                      to either next( ) or previous( ).
    
    
    Here is an example demonstrating both Iterator and ListIterator. It uses an ArrayList object, but the general principles apply to any type of collection.

    Of course, ListIterator is available only to those collections that implement the List interface
    Eg:
        import java.util.*;
        public class DemoIterator {
        public static void main(String args[]) {
            // Create an array list
            ArrayList al = new ArrayList();
            // add elements to the array list
            al.add("A");
            al.add("B");
            al.add("C");
            al.add("D");
            al.add("E");
            al.add("F");
            al.add("***This is ListIterator type***");
            
            // Use iterator to display contents of al
            System.out.print("Original contents of al: ");
            Iterator itr = al.iterator();
            while(itr.hasNext()) {
            Object element = itr.next();
            System.out.print(element + " ");
            }
            System.out.println();
            
            // Modify objects being iterated
            ListIterator litr = al.listIterator();
            while(litr.hasNext()) {
            Object element = litr.next();
            litr.set(element + " next ");
            }
            System.out.print("Modified contents of al: ");
            itr = al.iterator();
            while(itr.hasNext()) {
            Object element = itr.next();
            System.out.print(element + " ");
            }
            System.out.println();
            // Now, display the list backwards
            System.out.print("Modified list backwards: ");
            while(litr.hasPrevious()) {
            Object element = litr.previous();
            System.out.print(element + " ");
            }
            System.out.println();
            }
        }
    
    
    Output :
    Original contents of al: A B C D E F ***This is ListIterator type***
    Modified contents of al: A next B next C next D next E next F next ***This is ListIterator type*** next
    Modified list backwards: ***This is ListIterator type*** next F next E next D next C next B next A next

    How to use a Comparator ?
    Both TreeSet and TreeMap store elements in sorted order. However, it is the comparator that defines precisely what sorted order means.
    This interface lets us sort a given collection any number of different ways. Also, this interface can be used to sort any instances of any class(even classes we cannot modify).

        S.No	 Methods	                                Description
       ------ --------------------  ---------------------------------------------------------------------------------------
        1	  Using Java Comparator	  Here is a list of all the methods with examples provided by Comparator Interface.
    
    
    Using Java Comparator :
    Both TreeSet and TreeMap store elements in sorted order. However, it is the comparator that defines precisely what sorted order means.
    The Comparator interface defines two methods: compare( ) and equals( ). The compare( ) method, shown here, compares two elements for order:

    compare Method :
        int compare(Object obj1, Object obj2)
    
    
    obj1 and obj2 are the objects to be compared. This method returns zero if the objects are equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned.
    By overriding compare( ), you can alter the way that objects are ordered. For example, to sort in reverse order, you can create a comparator that reverses the outcome of a comparison.

    equals Method :
    The equals( ) method, shown here, tests whether an object equals the invoking comparator:
        boolean equals(Object obj)
    
    
    obj is the object to be tested for equality. The method returns true if obj and the invoking object are both Comparator objects and use the same ordering. Otherwise, it returns false. Overriding equals( ) is unnecessary, and most simple comparators will not do so.
        import java.util.*;
        public class Dog implements Comparator< Dog >, Comparable< Dog >{
            private String name;
            private int age;
            //default constructor
            Dog(){    
            }
            Dog(String n, int a){
            name = n;
            age = a;
            }
            public String getDogName(){
            return name;
            }
            public int getDogAge(){
            return age;
            }
            // Overriding the compareTo method
            public int compareTo(Dog d){
            return (this.name).compareTo(d.name);
            }
            // Overriding the compare method to sort the age
            public int compare(Dog d, Dog d1){
            return d.age - d1.age;
            }
        }
    
    
    Here the above class Dog which contains constructor and methods will be accessed through MainDogClass by using :
        import java.util.*;
        public class MainDogClass{
            public static void main(String args[]){
            // Takes a list o Dog objects
            List< Dog > list = new ArrayList< Dog >();
            list.add(new Dog("Scooby",3));
            list.add(new Dog("Lanz",2));
            list.add(new Dog("Jimmy",10));
            list.add(new Dog("Tommy",4));
            list.add(new Dog("Puppy",1));
            Collections.sort(list);// Sorts the array list
            
            for(Dog a: list)//printing the sorted list of names
            System.out.print(a.getDogName() + "  ");
            
            // Sorts the array list using comparator
            Collections.sort(list, new Dog());
            System.out.println(" ");
            System.out.println("-------------------------------");
            for(Dog a: list)//printing the sorted list of ages
            System.out.print(a.getDogName()+":"+a.getDogAge() + "  ");
            }
        }
    
    
    Output :
    Jimmy Lanz Puppy Scooby Tommy
    -------------------------------
    Puppy:1 Lanz:2 Scooby:3 Tommy:4 Jimmy:10

    Note : Sorting of the Arrays class is as the same as the Collections.

    Conclusion :
    The Java collections framework gives the programmer access to prepackaged data structures as well as to algorithms for manipulating them. A collection is an object that can hold references to other objects. The collection interfaces declare the operations that can be performed on each type of collection.
    The classes and interfaces of the collections framework are in package java.util.



    GENERICS

    It would be nice if we could write a single sort method that could sort the elements in an Integer array, a String array or an array of any type that supports ordering.
    Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods or, with a single class declaration, a set of related types, respectively.
    Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time. Using Java Generic concept, we might write a generic method for sorting an array of objects, then invoke the generic method with Integer arrays, Double arrays, String arrays and so on, to sort the array elements.

    Generic Methods :
    You can write a single generic method declaration that can be called with arguments of different types. Based on the types of the arguments passed to the generic method, the compiler handles each method call appropriately.

    Following are the rules to define Generic Methods:
  • All generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example).
  • Each type parameter section contains one or more type parameters separated by commas. A type parameter, also known as a type variable, is an identifier that specifies a generic type name.
  • The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.
  • A generic method's body is declared like that of any other method. Note that type parameters can represent only reference types, not primitive types (like int, double and char).

  • Eg:
        import java.util.ArrayList;
        import java.util.Collections;
        import java.util.List;
        public class GenericMethodTest{
          public static< E >void printArray( E[] inputArray ){
          for( E element : inputArray ){
          System.out.printf("%s ", element );
          }
          System.out.println();
          }
          public static void main(String args[]){
          Integer[] intArray ={5,10,15,20,25};
          Double[] doubleArray ={10.1,10.2,10.3,10.4};
          Character[] charArray ={'G','E','N','E','R','I', 'C','S'};
          System.out.println("Array integerArray contains:");
          printArray( intArray );// pass an Integer array
          System.out.println("\nArray doubleArray contains:");
          printArray( doubleArray );// pass a Double array
          System.out.println("\nArray characterArray contains:");
          printArray( charArray );// pass a Character array
          }
        }
    
    
    Output :
    Array integerArray contains:
    5 10 15 20 25

    Array doubleArray contains:
    10.1 10.2 10.3 10.4

    Array characterArray contains:
    G E N E R I C S

    Bounded Type Parameters :
    There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for. To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound.
    Eg:
    Following example illustrates how extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces). This example is Generic method to return the largest of three Comparable objects:
        import java.util.*;
        public class MaximumTest{
          // find the largest of three Comparable objects
          public static< T extends Comparable> T maximum(T x, T y, T z){
          T max = x;// assume x as largest
          if( y.compareTo( max )>0)
            max = y;// now y is the largest 
          
          if( z.compareTo( max )>0)
          max = z;// now z is the largest
          return max;// returns the largest object
          }
          public static void main(String args[]){
          System.out.printf("Max of %d, %d and %d is : %d\n\n",20,10,5, maximum(20,10,5));
          System.out.printf("Max of %.1f,%.1f and %.1f is : %.1f\n\n",6.5,7.5,8.5, maximum(6.5,7.5,8.5));
          System.out.printf("Max of %s, %s and %s is : %s\n","pear","apple","orange", maximum("pear","apple","orange"));
          }
        }
    
    
    Output :
    Max of 20, 10 and 5 is : 20

    Max of 6.5,7.5 and 8.5 is : 8.5

    Max of pear, apple and orange is : pear

    Generic Classes :
    A generic class declaration looks like a non-generic class declaration, except that the class name is followed by a type parameter section.As with generic methods, the type parameter section of a generic class can have one or more type parameters separated by commas. These classes are known as parameterized classes or parameterized types because they accept one or more parameters.
        import java.util.*;
        public class Box{
            private T t;
            public void add(T t){
            this.t = t;
            }
            public T get(){
            return t;
            }
            public static void main(String[] args){
            Box< Integer > integerBox =new Box< Integer >();
            Box< String > stringBox =new Box< String >();
            integerBox.add(new Integer(10));
            stringBox.add(new String("Hello World"));
            System.out.printf("Integer Value : %d\n\n", integerBox.get());
            System.out.printf("String Value : %s\n", stringBox.get());
          }
        }
    
    
    Output :
    Integer Value : 10

    String Value : Hello World

    (Core Java -Exception)