The collections framework consists of several interfaces and classes (in the java.util package) that define data structures to store data, search for and retrieve data, and perform other operations on a collection efficiently. An example is the ArrayList class.
This class implements the List interface in the collections framework. There are two primary interfaces in the collections framework from which all other interfaces are derived: Collection and Map. The Collection interface is extended by the Set and List interfaces.
The List, Set, and Map interfaces described as follows:
• The List interface: A list is a specific arrangement of elements in a collection. The elements in a list can access via their indices. This interface defines methods to read, add, and remove elements from the specified indices. The ArrayList and LinkedList classes implement this interface.
• The Set interface: The main feature of a set is that it cannot duplicate elements. It distinguishes it from a list in which duplicates are allowed. For example, consider a set of fingerprints in which each fingerprint is unique. The Set interface declares methods to check whether an element is present in a set and add and remove a specified element from a set. The HashSet, TreeSet, and LinkedHashSet classes implement this interface.
• The Map interface: A map associates a key with a value. It makes it possible to find and retrieve objects efficiently from a collection. For example, consider a world map. The key is the place’s coordinates on a map, and the value is the place’s name. Once you know the coordinates, you can locate the place quickly on the map.
The classes that implement the Map interface are TreeMap, HashMap, and LinkedHashMap.
The framework also contains other interfaces, such as Queue, Sorted Set, and SortedMap, and other classes, such as PriorityQueue.
We’ll be covering the following topics in this tutorial:
Need for Collection Framework:
JDK earlier than 1.2 or (Before Collection Framework), the standard library methods are built-in Java methods that are readily available for grouping Java objects (or collections) were Arrays or Vectors or Hashtables. All of these collections objects had no standard interface. Accessing elements of these Java objects was a hassle as each had a different method (and syntax) for accessing its members:
The main advantages of the Collections Framework in Java are as follows:
• Consistent API: The first benefit of the Collections Framework in Java is a consistent and regular API. The API provides a standard interface, Collection, Set, List, or Map. Java Collections Framework provides basic classes (ArrayList, LinkedList, Vector, etc.) and utility methods that implement these interfaces.
• Reduces programming effort: It gives core collection classes that reduce development effort, due to which we need not write our collection classes.
• Increases program speed and quality: Using the Java Collection Framework provides high-performance implementations of the interfaces that increase the performance.
Disadvantages of collections framework:
• Collections Framework must typecast objects or references to correct data types.
• Collections Framework can’t do compile-time type checking.
Hierarchy of Collection Framework
The Collection framework’s hierarchy consists of four core interfaces such as Collection, List, Set, Map, and two specialized interfaces named SortedSet and SortedMap for sorting. The java.util package contains all the interfaces and classes for the collection framework.
Methods of Collection interface
There are many methods declared in the Collection interface. They are as follows:
An iterator is an object that can be used to move sequentially through the data stored in a collection. You have already seen how the enhanced for loop can be used for the same purpose. An iterator is used when the elements in a collection have to be removed during traversal.Sets and lists provide an iterator, whereas maps do not. The iterator method returns an iterator to access the elements of a set.
Methods of Iterator interface
There are only three methods in the Iterator interface. They are:
The Collection Interface
Java specifies an interface called Collection that declares methods to manipulate a group of objects. Some methods in this interface are shown in the Figure below.
The List interface specifies methods to find and modify elements based on their position. Objects also have a given order in a Queue, but the ordering scheme is different from that in List.
The ArrayList and LinkedList classes implement the List interface. Like ArrayList, a LinkedList maintains the order in which elements are added to it. Another similarity is that in both types of lists, elements can access via their indices. The difference between the two is that an array list stores its elements in an array, whereas a linked list uses a group of connected nodes. Each node stores object data and linked to the previous and next node. (This configuration is analogous to how the cars in a train are connected.) A linked list is traversed by starting from either end and following the links from one node to the next. Array lists generally offer better performance than linked lists and tend to be used more often. Array lists provide faster random access of elements because, in them, an element can be accessed directly using its index, whereas, in a linked list, the intermediate nodes must be traversed before the required elements can be accessed. However, when elements need to be inserted or removed frequently from the middle of the List, a linked list can be faster than an array list.
ArrayList and LinkedList classes implement this interface. Examples of using an ArrayList are shown here:
ArrayList<Double> list1 = new ArrayList<Double>();
list1.add(10.5); // list1 = [10.5]
list1.add(30.5); // list1 = [10.5, 30.5]
list1.add(1, 20.5); // list1 = [10.5, 20.5, 30.5]
list1.set(2, 50.5); // list1 = [10.5, 20.5, 50.5]
System.out.println(list1); // list1 = [20.5, 50.5]
A LinkedList can be used similarly:
LinkedList<Double> list2 = new LinkedList<Double>();
list2.add(10.5); // list2 = [10.5]
list2.add(1, 20.5); // list2 = [10.5, 20.5]
System.out.println(list2); // list2 = [10.5]
The ArraList Class
The ArrayList class in java.util package used when we want an array whose size changes while the program executes. You know that arrays have a fixed size that must be specified when the array is created. How can an element be added to an array that filled? One way to do this is for the programmer to create a more extensive array and copy all of the smaller array elements into the larger one, with the remaining space for new elements. An alternative is to use the ArrayList class for arrays whose sizes change frequently. An instance of this class contains an array that grows and shrinks automatically as elements are added or removed to relieve the programmer from the burden of doing this.
The figure shows some of the constructors and methods in this class.
The following statements show how to use the add method:
ArrayList list = new ArrayList();
This prints out the size of list:
The size is 3 because 1ist has three elements: 100,200, and 300. Note that the length field is used to obtain the array size for a regular array, whereas the size method is used for an instance of the ArrayList class.
This removes the element at index 1:
list.remove (1) ;
The list now contains the elements 100 and 300, and has size 2.
The LinkedList class is built in class where data is stored as a separate objects i.e. each list element is stored along with a pointer to the object that precedes it and the object that follows it. With the help of these pointers, we can navigate through the entire list. As said earlier, it is because of these pointers that we can easily insert or delete an element from a linked list (just by adjusting the previous and next pointers of the element).
LinkedList <E> () Creates an empty linked list using the specified type.
Common methods of the LinkedList class
The Vector class provides the capability to implement a growable array. The array grows larger as more elements are added to it. The array may also be reduced in size, after some of its elements have been deleted. This is accomplished using the trimToSize() method.
Vector operates by creating an initial storage capacity and then adding to this capacity as needed. It grows by an increment defined by the increment variable. The initial storage capacity and increment can be specified in Vector’s constructor. There are three types of constructors:
Vector(int size, int increment)
The increment specifies the number of elements to allocate each time the vector is filled up to its capacity. In the default constructor, we don’t specify the initial capacity nor the increment so, it creates a default vector of the initial size of 10. All the vectors are created with an initial storage capacity, and objects are added to them. When the initial capacity is filled, and we attempt to store more objects in the vector, the vector allocates the space equal to that specified by increment. The increment is so selected that it allocates space to the new objects and still has some extra space. Specifying more space reduces the overhead of allocating space every time. If we don’t specify the increment, the vector size is doubled every time its capacity is filled.
The Stack class provides the capability to create and use stacks within the Java programs. Stacks are· storage objects that store information by pushing it onto a stack and remove and retrieve information by popping it off the stack. Stacks implement a last-in-first-out storage capability: The last object pushed on a stack is the first object that can be retrieved from the stack. The Stack class extends the Vector class.
The Stack class provides a single default constructor, Stack(), that is used to create an empty stack.
Objects are placed on the stack using the pushO method and retrieved from the stack using the pop() method.
search() – It allows us to search through a stack to see if a particular object is contained on the stack.
peek() – It returns the top element of the stack without popping it off.
empty() – It is used to determine whether a stack is empty.
The pop() and peek() methods both throw the EmptyStackException if the stack is empty. Use of the empty() method can help to avoid the generation of this exception.
The Set Interface
The Set interface also has special methods (inherited from Collection) to perform operations such as finding the intersection and union of the elements of two sets. All methods that modify the contents of a collection (such as add and remove in the Set interface) are optional methods. A class that extends an interface must implement all the methods in that interface; however, it is not necessary for a class to implement optional methods. If an instance of a class invokes a method that is not implemented in that class, an UnsupportedOperationException is thrown.