Generics and Collections in Java
Generics and Collections in Java
DATE: 30/09/2024
Generics in Java
Generics - Introduction
• When using Java, we often write classes and algorithms that work around certain data types. Let’s
look at the following class as an example:
• In the example above, we have a StringBox class which represents a real-world box of words.
• This class’s methods perform all of their computations with regards to the String myString field.
What if we wanted a box of ints? We could create a new class:
Generics - Introduction
• The example above meets our requirements, but as the program grows and we need more types of
boxes, it will become unmanageable. We can solve this problem by using generics.
• Generics, like the name implies, allow us to create generic classes and methods by specifying a type
parameter. We can make StringBox and IntegerBox into a generic Box class like so:
• In the example above, we created a generic Box class with a type parameter T. All class methods
perform their computation around the T-type parameter We can now specify that we want a String,
Integer, or any other type of Box by specifying a type argument.
Generics - Introduction
public class Box <T> {
private T data;
public Box(T data) {
this.data = data;
}
public T getData() {
return this.data;
}
}
• In the example above, notice that:
• The type parameter must be specified within the diamond operator (<>) after the class name.
• The type parameter, T, is similar to a method parameter but instead receives a class or interface
type as an argument as opposed to a reference or primitive type.
Generics - Introduction
• The constructor accepts a T-type parameter to initialize data.
• The getter method returns the type parameter T when returning data.
• In the example above, the object myStringBox is created like a non-generic object, but differs in:
• Needing the diamond operator with the class or interface type argument, <String> in this example,
• Needing the empty diamond operator before calling the constructor new Box<>("Apple").
Generics - Introduction
• it’s best practice to make them single, uppercase letters to easily distinguish them from the names of
classes or variables.
• By convention, type parameters are E (Elements), K (Key), N (Number), T (Type), V (Value), and S (or
Generics - Introduction
// Storage class into a generic class so that it can // Storage an Integer
store values of any type
Storage<Integer> integerStorage = new
public class Storage<T> { Storage<>();
private T value;
integerStorage.setValue(123);
public void setValue(T value) { Integer intValue = integerStorage.getValue();
this.value = value;
} System.out.println("Integer Value: " + intValue);
// Storage an string
public T getValue() {
return value; Storage<String> stringStorage = new
} Storage<>();
}
stringStorage.setValue("Hello");
String strValue = stringStorage.getValue();
System.out.println("String Value: " + strValue);
Generics - Introduction
Generics Method
• Like the generic class, we can create a generic method that can accept any type of arguments.
DATE:
Collections in Java
Collections - Introduction
• Used to standardize the way in which objects are handled in the class.
• Linked list - browsing history, trains coaches who are connected to each other, etc.
• Stacks - stack of plates or trays in which the topmost one gets picked first.
• Queue - same as the real-life queues, the one who enters the queue first, leaves it first too.
Collections - Introduction
• The Java Collections Framework - unified architecture for representing and manipulating
collection
• Standardizes the way in which groups of objects are handled by your programs
• Hierarchy of interfaces and classes that provides easy management of a group of objects.
• Java provided ad hoc classes such as Dictionary, Vector, Stack and Properties to store and
Collections - Introduction
• First, the framework had to be high-performance. The implementations for the fundamental
collections (dynamic arrays, linked lists, trees, and hash tables) are highly efficient.
• Second, the framework had to allow different types of collections to work in a similar manner and with
• Root interface for the entire collections framework and Used to iterate over the elements of the
collections.
• The Collection interface is the foundation upon which the Collections Framework is built because
interface Collection<E>
Here, E specifies the type of objects that the collection will hold.
• It provides basic operations like adding, removing, clearing the elements in a collection,
• In addition to the collection interfaces, collections also use the Comparator, RandomAccess,
• By implementing RandomAccess, a list indicates that it supports efficient, random access to its
elements.
• To provide the greatest flexibility in their use, the collection interfaces allow some methods to be
optional.
• Collections that do not allow their contents to be changed are called unmodifiable.
UnsupportedOperationException is thrown.
• Collection declares the core methods that all collections will have. These methods are
• The List interface extends Collection and declares the behavior of a collection that stores a
sequence of elements.
• Elements can be inserted or accessed by their position in the list, using a zero-based index.
• List is used to store ordered collection of data and it may contain duplicates elements.
interface List<E>
Here, E specifies the type of objects that the list will hold.
• In addition to the methods defined by Collection, List defines some of its own
• In addition to the methods defined by Collection, List defines some of its own
• The ArrayList class extends AbstractList and implements the List interface.
class ArrayList<E>
Here, E specifies the type of objects that the list will hold.
• ArrayList supports dynamic arrays that can grow as needed (increase or decrease in size)
• In Java, standard arrays are of a fixed length. After arrays are created, they cannot grow or shrink,
which means that you must know in advance how many elements an array will hold.
• The Collections Framework defines ArrayList which is a variable-length array of object references.
• ArrayList cannot be used for primitive data types like int, char, etc. , we need to use a wrapper class.
/* Create a class called Student with fields for storing a student's name, roll number, and course name.Implement
import java.util.ArrayList;
import java.util.Scanner;
class Student {
this.name = name;
this.rollNumber = rollNumber;
this.courseName = courseName;
}
33 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
return rollNumber;
return "Name: " + name + ", Roll Number: " + rollNumber + ", Course: " + courseName;
public StudentManagementSystem() {
students.add(student);
if (student.getRollNumber() == rollNumber) {
students.remove(student);
return;
if (student.getRollNumber() == rollNumber) {
System.out.println(student);
return;
if (students.isEmpty()) {
} else {
System.out.println(student);
System.out.println("All students:");
system.displayAllStudents();
system.searchStudent(102);
// Remove a student
system.removeStudent(101);
system.displayAllStudents();
}
40 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
// Using Array and finding the average of numbers numbers[i] = scanner.nextInt(); // Fill array with
import java.util.Scanner; user input
public class AverageOfNumbersArray { sum += numbers[i]; // Add to sum
public static void main(String[] args) { }
Scanner scanner = new Scanner(System.in); // Calculate average
System.out.print("Enter the number of integers you want to
double average = (double) sum / n;
average: ");
int n = scanner.nextInt(); // Display the average
int[] numbers = new int[n]; // Array to hold integers System.out.println("Average of the entered
int sum = 0;
integers is: " + average);
// Populate the array with integers and calculate the sum
for (int i = 0; i < n; i++) { }
System.out.print("Enter integer " + (i + 1) + ": "); }
• The LinkedList class extends AbstractSequentialList and implements the List, Deque, and Queue
interfaces.
• It provides a linked-list data structure (elements are called as nodes) that is Elements are not
stored in a contiguous memory.
• LinkedList uses Doubly Linked List to store its elements while ArrayList internally uses a dynamic
array to store its elements.
• LinkedList is non-synchronized means multiple threads at a time can access the code
class LinkedList<E>
Here, E specifies the type of objects that the list will hold.
• LinkedList()
builds a linked list that is initialized with the elements of the collection c
/* Create a program that allows users to add names, remove names, and display the list of
names using a LinkedList*/
import java.util.LinkedList;
import java.util.Scanner;
public class NameManager {
public static void main(String[] args) {
LinkedList<String> names = new LinkedList<>(); // Create a LinkedList to hold names
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("\nMenu:");
System.out.println("1. Add Name");
System.out.println("2. Remove Name");
System.out.println("3. Display Names");
System.out.println("4. Exit");
46 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
switch (choice) {
case 1: // Add Name
System.out.print("Enter name to add: ");
String nameToAdd = scanner.nextLine();
names.add(nameToAdd); // Add name to the LinkedList
System.out.println(nameToAdd + " has been added.");
break;
• Dynamic Size: Unlike arrays, a LinkedList can grow and shrink in size dynamically.
LinkedList than in an array or an ArrayList, especially for large lists, as it does not require
shifting elements.
• Vector uses a dynamic array to store the data elements and it is similar to ArrayList.
• It is synchronized and contains many methods that are not the part of Collection framework.
size, increment specifies number of elements to allocate each time that vector gets resized upward
v.remove("A");
System.out.println("Elements in the vector after remove "+v);
System.out.println("Size of the vector after the removal is "+v.size());
}
}
Output:
Size of the vector is 0
Elements in the vector [A, B, C, D]
Size of the vector is 4
Elements in the vector after remove [B, C, D]
Size of the vector after the removal is 3
• The stack contains all of the methods of Vector class and also provides its methods like boolean
• Stack is thread-safe
1. ArrayList
• Scenario: When you need fast access to elements by index and have a relatively stable size or need
occasional resizing.
• Use Case:
– Implementing a dynamic array where you frequently read elements using their index.
– When the application requires iterating over elements, as ArrayList provides good performance in
traversal.
• Advantages:
• Disadvantages:
– Insertion and deletion operations can be costly (O(n)) if they occur at arbitrary positions since
elements may need to be shifted.
NOTE:
• Because the internal array is stored as a continuous block, access to elements by index is
constant time (O(1)). This is one of the primary advantages of using an ArrayList over other
collections like LinkedList.
• The JVM can quickly compute the memory address of any element in the array using the formula:
• This formula allows for fast, direct access to elements at any index.
• It extends Collection and specifies the behavior of a collection that does not allow duplicate
elements.
• The add( ) method returns false if an attempt is made to add duplicate elements to a set.
• With two exceptions, it does not specify any additional methods of its own.
interface Set<E>
Here, E specifies the type of objects that the set will hold.
• It creates a collection that uses a hash table for storage which uses a mechanism called Hashing
class HashSet<E>
Here, E specifies the type of objects that the set will hold.
• In hashing, the informational content of a key is used to determine a unique value, called its hash
code.
• The hash code is then used as an index, at which the data associated with the key is stored.
• When we insert elements into the HashSet, it is not guaranteed that it gets stored in the same
• HashSet is non-synchronized means multiple threads at a time can access the code.
• HashSet does not define any additional methods beyond those provided by its superclasses and
interfaces.
hs.remove("Eta");
System.out.println("Elements in the HashSet after remove "+hs);
System.out.println("Size of the HashSet after the removal is "+hs.size());
}
}
Output:
Size of the HashSet is 0
Elements in the HashSet [Gamma, Eta, Alpha, Epsilon, Omega, Beta]
Size of the HashSet is 6
Elements in the HashSet after remove [Gamma, Alpha, Epsilon, Omega, Beta]
Size of the HashSet after the removal is 5
/*This example demonstrate finding the Intersection of two Arrays with collection*/
import java.util.HashSet;
import java.util.Set;
public class ArrayIntersection {
public static void main(String[] args) {
int[] array1 = {1, 3, 4, 5, 7};
int[] array2 = {3, 5, 6, 7, 8};
Set<Integer> intersection = findIntersection(array1, array2);
System.out.println("Intersection of two arrays: " + intersection);
}
public static Set<Integer> findIntersection(int[] array1, int[] array2) {
HashSet<Integer> set1 = new HashSet<>();
HashSet<Integer> resultSet = new HashSet<>();
• The LinkedHashSet class extends HashSet and adds no members of its own.
class LinkedHashSet<E>
Here, E specifies the type of objects that the set will hold.
• LinkedHashSet maintains a linked list of the entries in the set, in the order in which they were
inserted.
• LinkedHashSet is non-synchronized means multiple threads at a time can access the code
Output:
Size of the LinkedHashSet is 0
Elements in the LinkedHashSet [Alpha, Beta ,Gamma, Epsilon, Eta ,Omega]
Size of the LinkedHashSet is 6
Elements in the LinkedHashSet after remove [Alpha, Beta ,Gamma, Epsilon, Omega]
Size of the LinkedHashSet after the removal is 5
• The SortedSet interface extends Set and declares the behavior of a set sorted in ascending order.
interface SortedSet<E>
Here, E specifies the type of objects that the set will hold.
• In addition to those methods provided by Set, the SortedSet interface declares the methods
summarized
• In addition to the methods defined by Collection, Sorted Set defines some of its own
• The NavigableSet interface extends SortedSet and declares the behavior of a collection that
supports the retrieval of elements based on the closest match to a given value or values.
interface NavigableSet<E>
Here, E specifies the type of objects that the set will hold.
• Access and retrieval times are quite fast, which makes TreeSet an excellent choice when storing
large amounts of sorted information that must be found quickly.
class TreeSet<E>
Here, E specifies the type of objects that the set will hold.
• The Queue interface extends Collection and declares the behavior of a queue, which is often a first-
• There are types of queues in which the ordering is based upon other criteria. Queue is a generic
interface Queue<E>
Here, E specifies the type of objects that the queue will hold.
class PriorityQueue<E>
priorityQueue.add("d");
// Display elements of the priority queue
System.out.println("Elements in the priority queue:");
while (!priorityQueue.isEmpty()) {
System.out.println(priorityQueue.poll());
} Output:
} Elements in the priority queue:
} a
b
c
d
e
f
99 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
@Override
public int compareTo(Task other) {
// Higher priority tasks should come first
return Integer.compare(other.priority, this.priority);
}
}
• The Deque interface extends Queue and declares the behavior of a double-ended queue.
• Double-ended queues can function as standard, first-in, first-out queues or as last-in, first-out stacks.
interface Deque<E>
Here, E specifies the type of objects that the deque will hold.
• In addition to the methods that it inherits from Queue, Deque adds those methods summarized
• The ArrayDeque class extends AbstractCollection and implements the Deque interface.
class ArrayDeque<E>
ad.pop();
System.out.println("Elements in the ArrayDeque after remove "+ad);
System.out.println("Size of the ArrayDeque after the removal is "+ad.size());
}
}
Output:
Size of the ArrayDeque is 0
Elements in the ArrayDeque [D, C, B, A]
Size of the ArrayDeque is 4
Elements in the ArrayDeque after remove [C, B, A]
Size of the ArrayDeque after the removal is 3
• The maps interface in java is a collection that links a key with value pairs.
• Each entry in the map store the data in a key and its corresponding value.
• Map interface contains only unique keys and does not allow any duplicate keys.
• A key is an object that you use to access the value later, it is associated with a single value.
• A map is used when you need to search, edit, or remove elements based on a key.
• A Map cannot be traversed, therefore you must use the keySet() or entrySet() method to convert it
into a Set.
• There are two interfaces for implementing Map in java: Map and SortedMap, and three classes:
HashMap, LinkedHashMap, and TreeMap as follows:
Class Description
Interface Description
• To create an object, we always need a class that extends this map. Also, because Generics were
added in Java 1.5, it is now possible to restrict the types of objects that can be stored in the Map.
Syntax:
// Defining Type-safe Map
Map hm = new HashMap();
Example:
Map<String, String> hm = new HashMap<>();
• Each key can map to a maximum of one value, and a map cannot contain multiple keys. While
some implementations, like the HashMap and LinkedHashMap, allow null keys and null values,
others, like the TreeMap, do not.
• In the map interface in java, the order depends on the specific implementations. For eg,
TreeMap and LinkedHashMap have a predictable order, whereas HashMap does not.
• Java provides two interfaces for implementing Map. They consist of three classes: HashMap,
LinkedHashMap, and TreeMap as well as Map and a SortedMap.
• Set of keys, Set of Key-Value Mappings, and Collection of Values are the three collection views a
map interface provides.
• Since the Map interface is not a subtype of the Collection interface. Thus, it differs from the other
collection types in terms of features and behaviors.
• When someone has to retrieve and update elements based on keys or execute lookups by keys,
the maps are used. Additionally, For key-value association mapping like dictionaries, maps are
3.A map of school classes and the students names. Each key (class) is associated with a list of values
(student).
• The HashMap class extends AbstractMap and implements the Map interface.
• This allows the execution time of get( ) and put( ) to remain constant even for large sets.
Here, K specifies the type of keys, and V specifies the type of values
• It maintains a linked list of the entries in the map, in the order in which they were inserted.
• When iterating through a collection-view of a LinkedHashMap, the elements will be returned in the
order in which they were inserted.
• You can also create a LinkedHashMap that returns its elements in the order in which they were last
accessed.
Here, K specifies the type of keys, and V specifies the type of values.
• It ensures that the entries are maintained in ascending order based on the keys.
Here, K specifies the type of keys, and V specifies the type of values.
• The TreeMap class extends AbstractMap and implements the NavigableMap interface.
• A TreeMap provides an efficient means of storing key/value pairs in sorted order and allows rapid
retrieval.
• Unlike a hash map, a tree map guarantees that its elements will be sorted in ascending key order.
Here, K specifies the type of keys, and V specifies the type of values.
• Iterator is an object that implements either the Iterator or the ListIterator interface.
• ListIterator extends Iterator to allow bidirectional traversal of a list, and the modification of elements.
• Iterator and ListIterator are generic interfaces which are declared as shown here:
while(itr.hasNext()) {
String element = itr.next();
System.out.print(element+" ");
}
System.out.println();
System.out.println("Modified Contents of ArrayList in Backward using ListIterator");
while(litr.hasPrevious()) {
String element = litr.previous();
System.out.print(element+" ");
}
}
}
Output:
Initial Size of Array List is 0
After Insert the Size of Array List is 7
Contents of ArrayList using Iterator
CGAEBDF
Modified Contents of ArrayList using Iterator
C+ G+ A+ E+ B+ D+ F+
Modified Contents of ArrayList in Backward using ListIterator
F+ D+ B+ E+ A+ G+ C+
Spliterators
• JDK 8 added another type of iterator called a spliterator that is defined by the Spliterator interface.
• A spliterator cycles through a sequence of elements and it is similar to the iterators. However, the
• It provide support for parallel iteration of portions of the sequence. Thus, Spliterator supports parallel
programming.
• It offers a streamlined approach that combines the hasNext and next operations into one method.
interface Spliterator<T>
Method Description
default Comparator<? super T> If this Spliterator's source is SORTED by a Comparator, returns
getComparator() that Comparator.
default long Convenience method that returns estimateSize() if this Spliterator
getExactSizeIfKnown() is SIZED, else -1.
default boolean Returns true if this Spliterator's characteristics() contain all of the
hasCharacteristics given characteristics.
(int characteristics)
boolean tryAdvance If a remaining element exists, performs the given action on it,
(Consumer<? super T> action) returning true; else returns false.
Spliterator<T> trySplit() If this spliterator can be partitioned, returns a Spliterator covering
elements, that will, upon return from this method, not be covered by
this Spliterator.
Output:
Initial Size of Array List is 0
Contents of ArrayList using tryAdvance
1.0 2.0 3.0 4.0 5.0 6.0
Contents of ArrayList using forEachRemaining
1.0 2.0 3.0 4.0 5.0 6.0
Size of Array List after insertion is 6
Comparable
• Java Comparable interface is used to order the objects of the user-defined class.
• This interface is found in java.lang package and contains only one method named compareTo(Object).
• It provides a single sorting sequence only, i.e., we can sort the elements on the basis of single data
member only. For example, Sort based on student regno or name or any other member.
Syntax:
public int compareTo(Object obj)
• It is used to compare the current object with the specified object. It returns :
• Positive integer, if the current object is greater than the specified object.
• Negative integer, if the current object is less than the specified object.
Comparable
/***This Example demonstrate sorting using Comparable*/
•import
sdf java.io.*;
import java.util.*;
// A class 'Mobile' that implements Comparable
class Mobile implements Comparable<Mobile>{
private String name;
private int ram;
private int price;
Mobile(String name, int ram, int price){
this.name = name;
this.ram = ram;
this.price = price;
}
String getName() {
return name;
}
int getRam() {
return ram;
}
Comparable
void setRam(int ram) {
• sdf this.ram = ram;
}
void setName(String name) {
this.name = name;
}
int getPrice() {
return price;
}
void setPrice(int price) {
this.price = price;
}
//compare the current object with the specified object.
public int compareTo(Mobile o) {
if (this.ram > o.getRam())
return 1;
else
return -1;
}
}
Comparable
//Main Class
•class
sdf ComparableExample {
public static void main(String[] args) {
List<Mobile> mobileList = new ArrayList<>();
mobileList.add(new Mobile("RedMe", 16, 800));
mobileList.add(new Mobile("Apple", 8, 100));
mobileList.add(new Mobile("Samsung", 4, 600));
Collections.sort(mobileList);
System.out.println("Mobiles after sorting : ");
System.out.println("Name"+"\t"+"Ram"+"\t"+"Price");
for (Mobile mb : mobileList) {
System.out.println(mb.getName() + "\t" +
mb.getRam() + "\t" + mb.getPrice());
}
}
}
148 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
Comparator
• This interface is found in java.util package and contains the following method:
• compare(Object obj1,Object obj2) - It compares the first object with the second object.
• It provides multiple sorting sequences, i.e., we can sort the elements on the basis of any data member,
Comparator
/***This Example demonstrate sorting using Comparable and Comparator*/
• sdf
import java.io.*;
import java.util.*;
// A class 'Mobile' that implements Comparable
class Mobile implements Comparable<Mobile>{
private String name;
private int ram;
private int price;
Mobile(String name, int ram, int price){
this.name = name;
this.ram = ram;
this.price = price;
}
Comparator
String getName() {
• sdf return name;
}
int getRam() {
return ram;
}
int getPrice() {
return price;
}
//compare Mobiles by Ram size
public int compareTo(Mobile o) {
if (this.ram > o.getRam())
return 1;
else
return -1;
Comparator
// Class to compare Mobiles by price
• sdf
class PriceCompare implements Comparator<Mobile>{
public int compare(Mobile m1, Mobile m2){
if (m1.getPrice() < m2.getPrice()) return -1;
if (m1.getPrice() > m2.getPrice()) return 1;
else return 0;
}
}
// Class to compare Mobiles by name
class NameCompare implements Comparator<Mobile> {
public int compare(Mobile m1, Mobile m2) {
return m1.getName().compareTo(m2.getName());
}
}
Comparator
// Main class
• sdf
class ComparatorExample{
public static void main(String[] args){
List<Mobile> mobileList = new ArrayList<>();
mobileList.add(new Mobile("RedMe", 16, 800));
mobileList.add(new Mobile("Apple", 8, 100));
mobileList.add(new Mobile("Samsung", 4, 600));
System.out.println("Sorted by Price");
PriceCompare priceCompare = new PriceCompare();
Collections.sort(mobileList, priceCompare);
System.out.println("Mobiles after price sorting : ");
System.out.println("Name"+"\t"+"Ram"+"\t"+"Price");
for (Mobile mb : mobileList){
System.out.println(mb.getName() + "\t" +
mb.getRam() + "\t" +
mb.getPrice());
}
153 Collections in Java | © SmartCliff | Internal | Version 1.0
Collections in Java
Comparator
System.out.println("\nSorted by Name");
• sdf
NameCompare nameCompare = new NameCompare();
Collections.sort(mobileList, nameCompare);
System.out.println("Mobiles after price sorting : ");
System.out.println("Name"+"\t"+"Ram"+"\t"+"Price");
for (Mobile mb : mobileList){
System.out.println(mb.getName() + "\t" +
mb.getRam() + "\t" +
mb.getPrice());
}
Comparator
// Uses Comparable to sort by Ram
• sdf
System.out.println("\nSorted by Ram Size");
Collections.sort(mobileList);
System.out.println("Name"+"\t"+"Ram"+"\t"+"Price");
for (Mobile mb : mobileList){
System.out.println(mb.getName() + "\t" +
mb.getRam() + "\t" +
mb.getPrice());
}
}
}
Comparable Vs Comparator
Quiz
b) A group of Objects
Quiz
a) Array b) Vector
c) Stack d) HashSet
a) Array
Quiz
a) ArrayList b) HashSet
c) Queue d) TreeMap
c) Queue
Quiz
b) key-value pair
Quiz
a) ArrayList b) HashSet
c) LinkedList d) LinkedHashSet
Quiz
classes present?
a) java.net b) java.lang
c) java.awt d) java.util
d) java.util
Quiz
collection framework ?
a) SortedList b) Set
c) List d) SortedMap
a) SortedList
Quiz
a) Set b) Comparator
c) Collection d) List
d) List
Quiz
invoking collection ?
a) clear () b) reset ()
c) delete () d) refresh ()
a) clear ()
Quiz
10. What is the output of the following code
import java.util.*;
public class Test {
public static void main(String args[]) {
ArrayList <Integer> al = new ArrayList<Integer>();
for (int i = 5; i > 0; i--)
al.add(i);
for(Integer ele:al) {
System.out.print(ele+" ");
}
}
}
a) 12345 b) 54321
c) 13579 d) 02468