M1
M1
The collections and Framework: Collections Overview, The Collection Interfaces, The Collection
Classes, accessing a collection Via an Iterator, Storing User Defined Classes in Collections, The
Random Access Interface, Working with Maps, Comparators, The Collection Algorithms, Arrays, The
legacy Classes and Interfaces, Parting Thoughts on Collections.
Collections Overview
What is a Collection?
The term "Collection" in Java refers to a group of objects, known as elements, that are grouped
together. It represents a general concept of a container for objects.
Interfaces: These define the types of collections and the operations you can perform on
them. They are like blueprints or contracts that specify what methods a collection must have.
Collection: The root interface that represents a group of objects.
Efficiency: It provides optimized and well-tested data structures and algorithms, making your
code more efficient.
Reusability: You can use the same collection interfaces and classes for different types of data,
which makes your code more reusable.
Interoperability: Since collections in Java are standardized, they can easily work together and
with other parts of the Java API.
Reduced Effort: The framework provides ready-to-use implementations, so you don't need to
write your own data structures from scratch.
List: An ordered collection (like an array but dynamic in size). Examples: ArrayList, LinkedList.
Ordered collection
Allows duplicates
Indexed access
Methods: get(), set(), add(index, element)
Set: A collection that does not allow duplicate elements. Examples: HashSet, TreeSet.
No duplicates allowed
Unordered collection
Useful for uniqueness checks
Queue: A collection designed to hold elements before processing. It typically follows the FIFO
(First-In-First-Out) principle. Examples: LinkedList, PriorityQueue.
Methods: offer(), poll(), peek()
Map: A collection of key-value pairs, where each key is unique. Examples: HashMap,TreeMap.
Key-value pairs
Unique keys
Methods: put(), get(), remove()
a) ArrayList:
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.get(0); // Returns "Apple"
Key Characteristics:
b) LinkedList:
c) HashSet:
Key Characteristics:
d) HashMap:
Key Characteristics:
Not ordered:
Thread-unsafe
e) TreeSet:
Ordered
Slower than HashSet
Best for: Sorted unique elements
Common Operations:
a) Iteration:
// Using for-each
for (String item : list) {
System.out.println(item);
}
// Using Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
b) Sorting:
// For Lists
Collections.sort(list);
Collections.sort(list); // Sort
Collections.shuffle(list); // Random order
Collections.reverse(list); // Reverse order
Collections.binarySearch(list, key); // Binary search
Collections.max(list); // Find maximum
Collections.min(list); // Find minimum
Collections.frequency(list, element); // Count occurrences
Performance Considerations:
package Collections;
import java.util.*;
// 1. Adding elements
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add("Orange");
System.out.println("After adding elements: " + arrayList);
// 4. Accessing elements
String firstFruit = arrayList.get(0);
System.out.println("First fruit: " + firstFruit);
// 5. Updating elements
arrayList.set(1, "Kiwi");
System.out.println("After updating index 1 to Kiwi: " + arrayList);
// 6. Removing elements
arrayList.remove("Orange"); // Remove by object
arrayList.remove(0); // Remove by index
System.out.println("After removing elements: " + arrayList);
// 7. Searching elements
boolean containsKiwi = arrayList.contains("Kiwi");
int grapeIndex = arrayList.indexOf("Grape");
System.out.println("Contains Kiwi? " + containsKiwi);
System.out.println("Index of Grape: " + grapeIndex);
// 8. List size
System.out.println("List size: " + arrayList.size());
// 11. Sorting
Collections.sort(arrayList);
System.out.println("After sorting: " + arrayList);
// 12. Sublist
List<String> subList = arrayList.subList(0, 2);
System.out.println("Sublist (0-2): " + subList);
fruits.removeFirst();
fruits.removeLast();
System.out.println("After removing first and last: " + fruits);
}
}
o/p
=== ArrayList Demonstrations ===
After adding elements: [Apple, Banana, Orange]
After adding Mango at index 1: [Apple, Mango, Banana, Orange]
After adding multiple elements: [Apple, Mango, Banana, Orange, Grape, Pineapple]
First fruit: Apple
After updating index 1 to Kiwi: [Apple, Kiwi, Banana, Orange, Grape, Pineapple]
After removing elements: [Kiwi, Banana, Grape, Pineapple]
Contains Kiwi? true
Index of Grape: 2
List size: 4
Set interface
This program demonstrates the key features of the Set interface in Java. Here are the main concepts
covered:
1. Different Set Implementations:
HashSet (unordered, no duplicates)
TreeSet (sorted naturally)
LinkedHashSet (maintains insertion order)
2. Basic Operations:
Adding elements (add)
Removing elements (remove)
Checking existence (contains)
Clearing the set (clear)
3. Set Properties:
No duplicate elements
Different ordering behaviors based on implementation
Size and empty status checking
4. Set Operations:
Union (addAll)
Intersection (retainAll)
Difference (removeAll)
5. Iteration Methods:
Using for-each loop
Using Iterator interface
6. Bulk Operations:
Adding multiple elements
Converting to array
Working with collections
Program
package Collections;
import java.util.*;
// 1. Adding elements
System.out.println("\nAdding elements to HashSet:");
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Orange");
hashSet.add("Apple"); // Duplicate - will not be added
System.out.println("HashSet after adding elements: " + hashSet);
// 4. Removing elements
hashSet.remove("Banana");
System.out.println("After removing 'Banana': " + hashSet);
// 7. Set Operations
System.out.println("\n=== Set Operations Demonstration ===");
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));
// Union
Set<Integer> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println("Union of sets: " + union);
// Intersection
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println("Intersection of sets: " + intersection);
// Difference
Set<Integer> difference = new HashSet<>(set1);
difference.removeAll(set2);
System.out.println("Difference of sets (set1 - set2): " + difference);
// 8. Iteration Methods
System.out.println("\n=== Iteration Demonstration ===");
System.out.println("Using for-each loop:");
for (String element : hashSet) {
System.out.println(element);
}
System.out.println("\nUsing Iterator:");
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 9. Bulk Operations
Set<String> set3 = new HashSet<>();
set3.addAll(Arrays.asList("Apple", "Orange", "Grape"));
System.out.println("\nBulk addition: " + set3);
o/p
Queue interface
This program demonstrates the key features of the Queue interface in Java. Here are the main concepts
covered:
1. Basic Queue Operations (FIFO):
offer() - adds element
poll() - removes and returns head
peek() - views head without removal
2. ArrayDeque Features:
Supports both stack and queue operations
Can add/remove from both ends
More efficient than LinkedList for most operations
3. PriorityQueue:
Natural ordering
Custom ordering with Comparator
Maintains elements in priority order
4. Exception Handling:
Demonstrates difference between safe operations (offer/poll/peek) and throwing
operations (add/remove/element)
5. Additional Features:
Bulk operations
Array conversion
Size checking
Clear operation
Program
package Collections;
import java.util.*;
// Removing elements
String removed = queue.poll();
System.out.println("Removed element (poll): " + removed);
System.out.println("Queue after removal: " + queue);
// 2. ArrayDeque demonstration
System.out.println("\n=== ArrayDeque Demonstration ===");
ArrayDeque<String> arrayDeque = new ArrayDeque<>();
// Adding elements
arrayDeque.offer("First");
arrayDeque.offer("Second");
arrayDeque.offerLast("Last");
arrayDeque.offerFirst("New First");
System.out.println("ArrayDeque: " + arrayDeque);
// Examining elements
System.out.println("First element: " + arrayDeque.peekFirst());
System.out.println("Last element: " + arrayDeque.peekLast());
// Removing elements
System.out.println("Removed first: " + arrayDeque.pollFirst());
System.out.println("Removed last: " + arrayDeque.pollLast());
System.out.println("ArrayDeque after removal: " + arrayDeque);
// 3. PriorityQueue demonstration
System.out.println("\n=== PriorityQueue Demonstration ===");
// Natural ordering
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
// Adding elements
priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(3);
priorityQueue.offer(2);
priorityQueue.offer(4);
customPriorityQueue.offer("A");
customPriorityQueue.offer("BBB");
customPriorityQueue.offer("CC");
customPriorityQueue.offer("DDDD");
try {
// element() throws exception if queue is empty
System.out.println("Trying to get element from empty queue:");
exceptionQueue.element();
} catch (NoSuchElementException e) {
System.out.println("Exception caught: Queue is empty");
}
// 6. Bulk Operations
System.out.println("\n=== Bulk Operations ===");
Queue<String> bulkQueue = new LinkedList<>();
bulkQueue.addAll(Arrays.asList("One", "Two", "Three"));
System.out.println("After bulk addition: " + bulkQueue);
o/p
Map Interface
This program demonstrates the key features of the Map interface in Java. Here are the main concepts
covered:
1. Different Map Implementations:
HashMap (unordered)
TreeMap (sorted by keys)
LinkedHashMap (maintains insertion order)
2. Basic Operations:
put() and putIfAbsent()
get() and getOrDefault()
remove() with key and key-value pair
clear()
3. Advanced Features:
Entry set iteration
Key set and values collection
Compute operations
Merge operations
4. Map Properties:
Size checking
Empty checking
Key/Value existence checking
5. Special Features:
LinkedHashMap with access order
TreeMap's natural ordering
Bulk operations
Custom merge strategies
Program
package Collections;
import java.util.*;
// 1. Basic Operations
// Adding elements
hashMap.put("Apple", 1);
hashMap.put("Banana", 2);
hashMap.put("Orange", 3);
System.out.println("Initial HashMap: " + hashMap);
// Updating value
hashMap.put("Apple", 5); // Updates existing value
System.out.println("After updating Apple's value: " + hashMap);
// putIfAbsent
hashMap.putIfAbsent("Apple", 10); // Won't update as key exists
hashMap.putIfAbsent("Grape", 4); // Will add new entry
System.out.println("After putIfAbsent operations: " + hashMap);
// 2. Accessing Elements
System.out.println("\nAccessing Elements:");
System.out.println("Value for Apple: " + hashMap.get("Apple"));
System.out.println("Value for missing key: " + hashMap.get("Mango"));
System.out.println("Value for missing key with default: " + hashMap.getOrDefault("Mango", 0));
// 3. Removing Elements
hashMap.remove("Banana");
System.out.println("After removing Banana: " + hashMap);
// Conditional remove
hashMap.remove("Apple", 5); // Removes only if value matches
System.out.println("After conditional remove: " + hashMap);
// 7. removing elements
scores.remove("David");
System.out.println("After removing David: " + scores);
linkedHashMap.put("A", 1);
linkedHashMap.put("B", 2);
linkedHashMap.put("C", 3);
System.out.println("Initial LinkedHashMap: " + linkedHashMap);
linkedHashMap.put("D", 4); // Will remove eldest entry
System.out.println("After adding D (notice removal of eldest): " + linkedHashMap);
// Merging maps
Map<String, Integer> map2 = new HashMap<>();
map2.put("B", 3);
map2.put("C", 4);
Accessing Elements:
Value for Apple: 5
Value for missing key: null
Value for missing key with default: 0
After removing Banana: {Apple=5, Grape=4, Orange=3}
After conditional remove: {Grape=4, Orange=3}
This comprehensive program demonstrates various Collection classes and their features. Here's a
breakdown of the key concepts covered:
Queue Implementation:
Map Implementation:
Sorting
Binary search
Min/max operations
Frequency counting
Shuffling
Unmodifiable collections
Synchronized collections
Comparable interface
equals() and hashCode()
Custom comparators
Example program
package Collections;
import java.util.*;
class IterationComparisionDemo {
public static void main(String[] args) {
// Creating a list of numbers for demonstration
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
// Reset list
numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
// Reset list
numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
// 6. Performance comparison
System.out.println("\n=== Performance Comparison ===");
List<Integer> largeList = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
largeList.add(i);
}
o/p
This program demonstrates the essential concepts for storing user-defined classes in collections. Here
are the key points:
Essential Method Overrides:
Important Features:
Duplicate handling
Custom sorting
Grouping objects
Using custom comparators
Best Practices:
package Collections;
import java.util.*;
// Getters
public int getId() { return id; }
public String getName() { return name; }
public double getSalary() { return salary; }
public String getDepartment() { return department; }
@Override
public String toString() {
return String.format("Employee{id=%d, name='%s', salary=%.2f, department='%s'}",
id, name, salary, department);
}
}
public class UserDefinedCollectionsDemo {
public static void main(String[] args) {
// Create some employee objects
Employee emp1 = new Employee(101, "John Doe", 50000, "IT");
Employee emp2 = new Employee(102, "Jane Smith", 60000, "HR");
Employee emp3 = new Employee(103, "Bob Wilson", 55000, "IT");
Employee emp4 = new Employee(101, "John Doe", 50000, "IT"); // Duplicate of emp1
Employee emp5 = new Employee(104, "Alice Brown", 65000, "Finance");
// 1. ArrayList Demo
System.out.println("=== ArrayList Demonstration ===");
List<Employee> employeeList = new ArrayList<>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
System.out.println("Employees in ArrayList:");
employeeList.forEach(System.out::println);
System.out.println("Employees in HashMap:");
employeeMap.forEach((id, emp) ->
System.out.println("Key: " + id + ", Value: " + emp));
// 6. PriorityQueue Demo
System.out.println("\n=== PriorityQueue Demonstration ===");
Queue<Employee> employeePQ = new PriorityQueue<>(
Comparator.comparingDouble(Employee::getSalary)
);
employeePQ.addAll(employeeSet);
employeePQ.add(emp5);
o/p
=== ArrayList Demonstration ===
Employees in ArrayList:
Employee{id=101, name='John Doe', salary=50000.00, department='IT'}
Employee{id=102, name='Jane Smith', salary=60000.00, department='HR'}
Employee{id=103, name='Bob Wilson', salary=55000.00, department='IT'}
Comparators
Comparators in Java are used to define custom sorting logic for objects. The Comparator interface has a
single method compare(T o1, T o2) that needs to be implemented.
The compare() method returns:
The example also demonstrates comparator chaining using thenComparing(), which allows you to
specify a secondary sorting criterion when the primary criterion results in a tie.
When you run this program, it will show the students sorted in different ways:
By age (ascending)
By GPA (descending)
By name (alphabetically)
By age and then GPA (combined sorting)
They provide more flexibility than implementing Comparable interface, as you can have multiple
sorting criteria
They can be passed to collection sorting methods like Collections.sort() or List.sort()
They can be stored in variables and reused
package Comparators;
import java.util.*;
// Getters
public String getName() { return name; }
public int getAge() { return age; }
public double getGpa() { return gpa; }
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + ", gpa=" + gpa + "}";
}
}
o/p
Sorted by age:
Student{name='Bob', age=19, gpa=3.5}
Student{name='Alice', age=20, gpa=3.8}
Student{name='David', age=20, gpa=3.7}
Student{name='Larance', age=20, gpa=3.9}
Student{name='Charlie', age=21, gpa=3.9}
Sorted by name:
Student{name='Alice', age=20, gpa=3.8}
Student{name='Bob', age=19, gpa=3.5}
Student{name='Charlie', age=21, gpa=3.9}
Student{name='David', age=20, gpa=3.7}
Student{name='Larance', age=20, gpa=3.9}
Searching:
Extreme Values:
Collection Wrappers:
Collection Composition:
Replacement Operations:
Program VI A,C
package Collections;
import java.util.*;
class CollectionsAlgorithmsDemo {
public static void main(String[] args) {
// Create sample lists for demonstration
List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 7, 1, 9, 4, 6, 2, 8, 5));
List<Integer> targetList = new ArrayList<>(Arrays.asList(10, 20, 30, 40, 50));
// 1. Sorting Algorithms
Collections.sort(numbers);
System.out.println("\n1. After sorting: " + numbers);
Collections.reverse(numbers);
System.out.println(" After reverse: " + numbers);
Collections.shuffle(numbers);
System.out.println(" After shuffle: " + numbers);
// 2. Searching Algorithms
Collections.sort(numbers); // Must sort before binary search
int searchKey = 6;
int position = Collections.binarySearch(numbers, searchKey);
System.out.println("\n2. Binary search for " + searchKey + ": found at index " + position);
// 8. Collection Composition
List<Integer> list3 = Arrays.asList(1, 2, 3);
List<Integer> list4 = Arrays.asList(4, 5, 6);
boolean addAll = new ArrayList<>(list3).addAll(list4);
System.out.println("\n8. After combining lists: " + addAll);
o/p
3. Minimum value: 1
Maximum value: 9
4. Frequency of 2: 3
Are lists disjoint? true
RandomAccess interface:
Purpose:
Key Characteristics:
When to Use:
Performance Implications:
Binary search
Random access iterations
Sorting algorithms
Best Practices:
Program VI B
package Collections;
import java.util.*;
class RandomAccessDemo {
// Utility method to measure access time using for loop (random access)
private static long measureRandomAccessTime(List<Integer> list) {
long startTime = System.nanoTime();
startTime = System.nanoTime();
Collections.binarySearch(linkedList, 50000);
System.out.println("LinkedList binary search time: " +
(System.nanoTime() - startTime) + " ns");
}
}
o/p
Vector:
Hashtable:
Dictionary:
Properties:
Extends Hashtable
Used for storing configuration settings
Key methods:
BitSet:
Enumeration Interface:
These classes are considered legacy but still supported for backward compatibility
Modern alternatives are generally preferred:
Program
package Collections;
import java.util.*;
// 2. Hashtable demonstration
System.out.println("\n2. Hashtable Example:");
Hashtable<Integer, String> hashtable = new Hashtable<>();
hashtable.put(1, "One");
hashtable.put(2, "Two");
hashtable.put(3, "Three");
System.out.println("Dictionary elements:");
Enumeration<Integer> dictKeys = dictionary.keys();
while (dictKeys.hasMoreElements()) {
Integer key = dictKeys.nextElement();
System.out.println("Key: " + key + ", Value: " + dictionary.get(key));
}
// 4. Stack demonstration
System.out.println("\n4. Stack Example:");
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("Stack elements:");
while (!stack.empty()) {
System.out.println("Popped: " + stack.pop());
}
// 5. Properties demonstration
System.out.println("\n5. Properties Example:");
Properties properties = new Properties();
properties.setProperty("database.url", "jdbc:mysql://localhost:3306/db");
properties.setProperty("database.user", "admin");
properties.setProperty("database.password", "password");
System.out.println("Properties elements:");
Enumeration<?> propertyNames = properties.propertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String) propertyNames.nextElement();
System.out.println(propertyName + " = " + properties.getProperty(propertyName));
}
// 6. BitSet demonstration
System.out.println("\n6. BitSet Example:");
BitSet bitSet = new BitSet(8);
bitSet.set(0); // Set first bit
bitSet.set(2); // Set third bit
bitSet.set(4); // Set fifth bit
System.out.println("BitSet elements:");
for (int i = 0; i < 8; i++) {
System.out.println("Bit " + i + " is set: " + bitSet.get(i));
}
}
}
o/p
1. Vector Example:
Vector size: 3
Vector capacity: 10
Vector capacity after trim: 3
2. Hashtable Example:
3. Dictionary Example:
Dictionary elements:
Key: 2, Value: Second
Key: 1, Value: First
4. Stack Example:
Stack elements:
Popped: 3
Popped: 2
Popped: 1
5. Properties Example:
Properties elements:
database.password = password
database.user = admin
database.url = jdbc:mysql://localhost:3306/db
6. BitSet Example:
BitSet elements:
Bit 0 is set: true
Bit 1 is set: false
Bit 2 is set: true
Bit 3 is set: false
Bit 4 is set: true
Bit 5 is set: false
Bit 6 is set: false
Bit 7 is set: false
Both Comparable and Comparator are interfaces in Java used to sort objects, but they serve different
purposes and are implemented differently.
Comparable
The Comparable interface is implemented by a class to define its "natural ordering." It has a single
method:
Key characteristics:
Example
package Comparable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
o/p
Student{name='Bob', rollNumber=101'}
Student{name='Charlie', rollNumber=102'}
Student{name='Alice', rollNumber=103'}
Comparator
The Comparator interface is external to the class being compared and defines custom ordering. It has a
primary method:
Key characteristics:
It's in the java.util package
Allows defining multiple different comparison strategies for the same class
Used with sort methods that accept a Comparator parameter
Example
package Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; // Missing import for Comparator
import java.util.List;
@Override
public String toString() {
return "Student{name='" + name + "', rollNumber=" + rollNumber + ", gpa=" + gpa + "}";
}
// Sort by name
Collections.sort(students, new NameComparator());
System.out.println("Sorted by name:"); // Missing print statement
for (Student s : students) {
System.out.println(s);
}
// Sort by GPA
Collections.sort(students, new GpaComparator());
System.out.println("\nSorted by GPA:");
for (Student s : students) {
System.out.println(s);
}
}
}
o/p
Sorted by name:
Student{name='Alice', rollNumber=103, gpa=3.8}
Student{name='Bob', rollNumber=101, gpa=3.9}
Student{name='Charlie', rollNumber=102, gpa=3.7}
Sorted by GPA:
Student{name='Bob', rollNumber=101, gpa=3.9}
Student{name='Alice', rollNumber=103, gpa=3.8}
Student{name='Charlie', rollNumber=102, gpa=3.7}
Parting Thoughts on Collections
The Collections Framework gives you, the programmer, a powerful set of well-engineered
solutions to some of programming’s most common tasks. Consider using a collection the
next time that you need to store and retrieve information. Remember, collections need not
be reserved for only the “large jobs,” such as corporate databases, mailing lists, or inventory
systems. They are also effective when applied to smaller jobs. For example, a TreeMap might
make an excellent collection to hold the directory structure of a set of files. A TreeSet could
be quite useful for storing project-management information. Frankly, the types of problems
that will benefit from a collections-based solution are limited only by your imagination.