Collections Framework-1
Collections Framework-1
The Iterable interface is the root interface for all the collection classes. The
Collection interface extends the Iterable interface and therefore all the subclasses
of Collection interface also implement the Iterable interface.
2. Collection interface extends the Iterable interface. The iterable interface has only
one method called iterator(). The function of the iterator method is to return the
iterator object. Using this iterator object, we can iterate over the elements of the
collection.
3. List, Queue, and Set have three components which extends the Collection
interface. A map is not inherited by Collection interface.
List Interface
1. This interface represents a collection of elements whose elements are arranged
sequentially ordered.
2. List maintains an order of elements means the order is retained in which we add
elements, and the same sequence we will get while retrieving elements.
3. We can insert elements into the list at any location. The list allows storing
duplicate elements in Java.
4. ArrayList, vector, and LinkedList are three concrete subclasses that implement
the list interface.
Set Interface
1. This interface represents a collection of elements that contains unique elements.
i.e, It is used to store the collection of unique elements.
2. Set interface does not maintain any order while storing elements and while
retrieving, we may not get the same order as we put elements. All the elements in
a set can be in any order.
3. Set does not allow any duplicate elements.
4. HashSet, LinkedHashSet, TreeSet classes implements the set interface and
sorted interface extends a set interface.
5. It can be iterated by using Iterator but cannot be iterated using ListIterator.
SortedSet Interface
1. This interface extends a set whose iterator transverse its elements according to
their natural ordering.
2. TreeSet implements the sorted interface.
Queue Interface
1. A queue is an ordered of the homogeneous group of elements in which new
elements are added at one end(rear) and elements are removed from the other
end(front). Just like a queue in a supermarket or any shop.
2. This interface represents a special type of list whose elements are removed only
from the head.
3. LinkedList, Priority queue, ArrayQueue, Priority Blocking Queue, and Linked
Blocking Queue are the concrete subclasses that implement the queue interface.
Deque Interface
1. A deque (double-ended queue) is a sub-interface of queue interface. It is usually
pronounced “deck”.
2. This interface was added to the collection framework in Java SE 6. Deque
interface extends the queue interface and uses its method to implement deque. The
hierarchy of the deque interface is shown in the below figure.
addAll(Collection c) : boolean
3. clear(): This method clears or removes all the elements from the collection. The
general form of this method is as follows:
clear() : void
This method returns nothing.
4. contains(): It checks that element is present or not in a collection. That is it is
used to search an element. The general for contains() method is as follows:
containsAll(Collection c) : boolean
6. equals(): It checks for equality with another object. The general form is as
follows:
hashCode() : int
8. isEmpty(): It returns true if a collection is empty. That is, this method returns
true if the collection contains no elements.
isEmpty() : boolean
9. iterator(): It returns an iterator. The general form is given below:
iterator() : Iterator
10. remove(): It removes a specified element from the collection. The general
syntax is given below:
removeAll(Collection c) : boolean
12. retainAll(): This method is used to remove all elements from the collection
except the specified collection. It returns true if all the elements are removed
otherwise returns false.
retainAll(Collection c) : boolean
13. size(): The size() method returns the total number of elements in the collection.
Its return type is an integer. The general syntax is given below:
size() : int
14. toArray(): It returns the elements of a collection in the form of an array. The
array elements are copies of the collection elements.
toArray() : Object[]
15. Object[ ] toArray(): Returns an array that contains all the elements stored in
the invoking collection. The array elements are the copies of the collection
elements.
LinkedList
It is the most commonly used data structure that implements a doubly linked list to
store the elements inside it. It can store duplicate elements. It implements the
Dequeue interface extended by the Queue interface and the List interface. It is not
synchronized. Now let’s see how to solve our problem discussed above (the FIFO
concept) using LinkedList. The problem is to serve the customers in a manner they
arrive i.e first in first out.
Example
import java.util.*;
public class TestJavaCollection2{
public static void main(String args[]){
LinkedList<String> al=new LinkedList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ravi");
al.add("Ajay");
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
ArrayList
It simply implements the List interface. It maintains the insertion order and uses a
dynamic array to store elements of different data types. Elements can be
duplicated. It is also non-synchronized and can store null values. Now let’s see its
different methods... These are useful when we do not know how many records or
elements we need to insert. Let’s take an example of a library where we don’t
know how many books we have to keep. So whenever we have a book, we need to
insert it into ArrayList.
Example
import java.util.*;
class TestJavaCollection1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Ravi");//Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
//Traversing list through Iterator
Iterator itr=list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
HashSet
It implements the Set interface and never contains duplicate values. It implements
the hash table for storing the values. It also allows null values. It never maintains
the insertion order but provides the constant time performance for add, remove,
size, and contains methods. It is best for search operations and it is not
synchronized.
Example
import java.util.*;
class HashSetExample{
public static void main(String args[]){
//creating HashSet and adding elements to it
HashSet<Integer> hashSet=new HashSet();
hashSet.add(1);
hashSet.add(5);
hashSet.add(4);
hashSet.add(3);
hashSet.add(2);
//getting an iterator for the collection
Iterator<Integer> i=hashSet.iterator();
//iterating over the value
while(i.hasNext()) {
System.out.println(i.next());
}
}
}
Output
12345
As you can see it does not maintains the insertion order.
ArrayDeque
It implements the Deque interface so it allows operations from both ends. It does
not allow null values. It is faster than Stack and LinkedList when implemented as
Stack and LinkedList. ArrayDeque has no size restrictions as it grows and shrinks
as per the requirements. It is unsynchronized, meaning it is not thread-safe. To
keep it thread-safe we have to implement some external logic.
Example
import java.util.*;
public class ArrayDequeExample {
public static void main(String[] args) {
//creating Deque and adding elements
Deque<String> deque = new ArrayDeque<String>();
//adding an element
deque.add("One");
//adding an element at the start
deque.addFirst("Two");
//adding an element at the end
deque.addLast("Three");
//traversing elements of the collection
for (String str : deque) {
System.out.println(str);
}
}
}
Output
Two One Three
HashMap
It is the implementation of the Map interface backed by the hash table. It stores the
key-value pairs. It does not allow null values. It is not synchronized. It never
guarantees the insertion order. It provides constant time performance for methods
like get, and put. Its performance depends on two factors — initial capacity and
load factor. Capacity is the number of buckets in the hash table so the initial
capacity is the number of buckets allocated at the time of creation. Load factor is
the measure of how much a hash table can be populated before its capacity is
increased. The rehash method is used to increase the capacity and it mainly doubles
the number of buckets.
Example
import java.util.*;
public class HashMapExample{
public static void main(String args[]){
//creating a HashMap
HashMap<Integer,String> map=new HashMap<Integer,String>();
//putting elements into the map
map.put(1,"England");
map.put(2,"USA");
map.put(3,"China");
Method Description
boolean hasNext(
Returns true if there are more elements in the collection. Otherwise, returns false.
)
E next() Returns the next element present in the collection. Throws NoSuchElementException if th
void remove() Removes the current element. Throws IllegalStateException if an attempt is made to call re
preceded by a call to next() method.
Iterator Example
In this example, we are using iterator() method of collection interface that returns
an instance of Iterator interface. After that we are using hasNext() method that
returns true of collection contains an elements and within the loop, obtain each
element by calling next() method.
import java.util.*;
class Demo
{
public static void main(String[] args)
{
ArrayList< String> ar = new ArrayList< String>();
ar.add("ab");
ar.add("bc");
ar.add("cd");
ar.add("de");
Iterator it = ar.iterator(); //Declaring Iterator
while(it.hasNext())
{
System.out.print(it.next()+" ");
}
}
}
Method Description
void add(E obj) Inserts obj into the list in front of the element that will be returned by the next call to ne
boolean hasNext() Returns true if there is a next element. Otherwise, returns false.
boolean hasPrevious(
Returns true if there is a previous element. Otherwise, returns false.
)
E next() Returns the next element. A NoSuchElementException is thrown if there is not a next e
int nextIndex() Returns the index of the next element. If there is not a next element, returns the size of
int previousIndex() Returns the index of the previous element. If there is not a previous element, returns -1
void remove() Removes the current element from the list. An IllegalStateException is thrown if remov
next() or previous() method is invoked.
void set(E obj) Assigns obj to the current element. This is the element last returned by a call to either n
ListIterator Example
import java.util.*;
class Demo
{
public static void main(String[] args)
{
ArrayList< String> ar = new ArrayList< String>();
ar.add("ab");
ar.add("bc");
ar.add("cd");
ar.add("de");
ListIterator litr = ar.listIterator();
while(litr.hasNext()) //In forward direction
{
System.out.print(litr.next()+" ");
}
while(litr.hasPrevious()) //In backward direction
{
System.out.print(litr.previous()+" ");
}
}
}
ab bc cd de de cd bc ab
for-each loop
for-each version of for loop can also be used for traversing the elements of a
collection. But this can only be used if we don't want to modify the contents of a
collection and we don't want any reverse access. for-each loop can cycle through
any collection of object that implements Iterable interface.
Exmaple:
import java.util.*;
class Demo
{
public static void main(String[] args)
{
LinkedList< String> ls = new LinkedList< String>();
ls.add("a");
ls.add("b");
ls.add("c");
ls.add("d");
for(String str : ls)
{
System.out.print(str+" ");
}
}
}
abcd
we can use for loop to traverse the collection elements but only index-based
collection can be accessed. For example, list is index-based collection that allows
to access its elements using the index value.
import java.util.*;
class Demo
{
public static void main(String[] args)
{
LinkedList<String> ls = new LinkedList<String>();
ls.add("a");
ls.add("b");
ls.add("c");
ls.add("d");
for(int i = 0; i<ls.size(); i++)
{
System.out.print(ls.get(i)+" ");
}
}
}
abcd
Java Map Interface
A Map in Java is an object that maps keys to values and is designed for the
faster lookups. Data is stored in key-value pairs and every key is unique. Each
key maps to a value hence the name map. These key-value pairs are called map
entries.
The Map interface is not a true subtype of Collection interface, therefore, its
characteristics and behaviors are different from the rest of the collection
types.
It provides three collection views – set of keys, set of key-value mappings
and collection of values.
A Map cannot contain duplicate keys and each key can map to at most one
value. Some implementations allow null key and null
value (HashMap and LinkedHashMap) but some does not (TreeMap).
The Map interface doesn’t guarantee the order of mappings, however, it
depends on the implementation. For instance, HashMap doesn’t guarantee
the order of mappings but TreeMap does.
AbstractMap class provides a skeletal implementation of the Java Map
interface and most of the Map concrete classes extend AbstractMap class
and implement required methods.
Now that you have an idea of what Map interface in Java is, let’s go ahead and
check out the hierarchy of Java Map.
There are two interfaces that implement the Map in java: Map and SortedMap.
And popular implementation classes of Map in Java are HashMap, TreeMap,
and LinkedHashMap. The hierarchy of Java Map is given below:
Methods Description
public put(Object key, Object value) This method inserts an entry in the map
public void putAll(Map map) This method inserts the specified map
in this map
It is used to delete an entry for the
public Object remove(Object key)
specified key
It returns the Set view containing all the
public Set keySet()
keys
It returns the Set view containing all the
public Set entrySet()
keys and values
void clear() It is used to reset the map
It inserts the specified value with the
public void putIfAbsent(K key, V value) specified key in the map only if it is not
already specified
public Object get(Object key) It returns the value for the specified key
public boolean containsKey(Object key) It is used to search the specified key
from this map
HashMap Class
The most common class that implements the Java Map interface is the HashMap.
It is a hash table based implementation of the Map interface. It implements all of
the Map operations and allows null values and one null key. Also, this class does
not maintain any order among its elements. Here’s an example program
demonstrating the HashMap class.
import java.util.*;
public class HashMapExample1
{
public static void main(String args[])
{
HashMap<Integer,String> map=new HashMap<Integer,String>
();//Creating HashMap
map.put(1,"Mango"); //Put elements in Map
map.put(2,"Apple");
map.put(3,"Banana");
map.put(4,"Grapes");
System.out.println("Iterating Hashmap...");
for(Map.Entry m : map.entrySet())
{
System.out.println(m.getKey()+" "+m.getValue());
}
}
}
TreeMap Class
This implementation uses the Red-Black tree as the underlying data structure. A
TreeMap is sorted according to the natural ordering of its keys, or by a Comparator
provided at creation time. This implementation doesn’t allow nulls but
maintains order on its elements. Here’s an example program demonstrating the
TreeMap class.
import java.util.*;
public class TreeMap2
{
public static void main(String args[])
{
TreeMap<Integer,String> map=new TreeMap<Integer,String>(
);
map.put(100,"Amit");
map.put(102,"Ravi");
map.put(101,"Vijay");
map.put(103,"Rahul");
System.out.println("Before invoking remove() method");
for(Map.Entry m:map.entrySet())
{
System.out.println(m.getKey()+" "+m.getValue());
}
map.remove(102);
System.out.println("After invoking remove() method");
for(Map.Entry m:map.entrySet())
{
System.out.println(m.getKey()+" "+m.getValue());
}
}
}
LinkedHashMap Class
As the name indicates this implementation of Java Map interface uses a hash table
and a linked list as the underlying data structures. Thus the order of a
LinkedHashMap is predictable, with insertion-order as the default order. Also,
allows nulls like in HashMap. Here’s an example program demonstrating the
TreeMap class
import java.util.*;
public class LinkedHashMap3
{
public static void main(String args[])
{
Map<Integer,String> map=new LinkedHashMap<Integer,Strin
g>();
map.put(101,"Amit");
map.put(102,"Vijay");
map.put(103,"Rahul");
System.out.println("Before invoking remove() method: "+map);
map.remove(102);
System.out.println("After invoking remove() method: "+map);
}
}
Java Generics
Java Generics allows us to create a single class, interface, and method that can be
used with different types of data (objects).
Note: Generics does not work with primitive types (int, float, char, etc).
We can create a class that can be used with any type of data. Such a class is known
as Generics Class.
Here's is how we can create a generics class in Java:
In the above example, we have created a generic class named GenericsClass. This
class can be used to work with any type of data.
Here, T used inside the angle bracket <> indicates the type parameter. Inside
the Main class, we have created two objects of GenericsClass
intObj - Here, the type parameter T is replaced by Integer. Now,
the GenericsClass works with integer data.
stringObj - Here, the type parameter T is replaced by String. Now,
the GenericsClass works with string data.
Similar to the generics class, we can also create a method that can be used with any
type of data. Such a class is known as Generics Method.
class DemoClass {
Here, the type parameter <T> is inserted after the modifier public and before the
return type void.
We can call the generics method by placing the actual
type <String> and <Integer> inside the bracket before the method name.
Bounded Types
In general, the type parameter can accept any data types (except primitive types).
However, if we want to use generics for some specific types (such as accept data of
number types) only, then we can use bounded types.
In the case of bound types, we use the extends keyword. For example,
class Main {
public static void main(String[] args) {
Here, GenericsClass is created with bounded type. This means GenericsClass can
only work with data types that are children of Number (Integer, Double, and so
on).
However, we have created an object of the generics class with String. In this case,
we will get the following error.
1. Code Reusability
With the help of generics in Java, we can write code that will work with different
types of data. For example,
Here, we have created a generics method. This same method can be used to
perform operations on integer data, string data, and so on.
The type parameter of generics provides information about the type of data used
in the generics code. For example,
// using Generics
GenericsClass<Integer> list = new GenericsClass<>();
The collections framework uses the concept of generics in Java. For example,
In the above example, we have used the same ArrayList class to work with
different types of data.
Similar to ArrayList, other collections (LinkedList, Queue, Maps, and so on) are
also generic in Java.