Object Oriented Programming With JavaUnit 912 min read
Collections, Generics & Java Data Structures: Lists, Sets, Maps & Type Safety
Unit 9 of Object Oriented Programming With Java covers Java’s Collections Framework (List, Set, Map, Queue), generics for type-safe programming, autoboxing/unboxing, and real-world applications like eSewa’s transaction queues and Daraz’s inventory management.
TAKEAWAYS:
- Collections Framework provides ready-to-use data structures (ArrayList, HashSet, HashMap) to store and manipulate groups of objects efficiently.
- Generics enable type-safe programming by allowing classes/methods to operate on objects of any type while enforcing compile-time checks.
- Autoboxing/Unboxing automatically converts between primitive types and their wrapper classes (e.g.,
int↔Integer), but generics bypass this for strict type safety. - Common Interfaces like
List,Set, andMapdefine behaviors for collections, while implementations likeArrayListorHashMapprovide concrete functionality. - Real-world use: eSewa uses
Queuefor transaction processing, Daraz usesHashMapfor inventory tracking, and banks useListfor transaction history. - Exam focus: Write generic methods/classes, explain autoboxing vs. generics, and compare
List,Set, andMapwith code examples and traces.
1. Introduction to Collections Framework
Java’s Collections Framework is a unified architecture for storing and manipulating groups of objects. It provides:
- Interfaces (e.g.,
List,Set,Map) defining behaviors. - Implementations (e.g.,
ArrayList,HashSet,HashMap) providing concrete functionality. - Algorithms (e.g., sorting, searching) to perform operations on collections.
Why Use Collections?
- Avoid manual array management (fixed size, primitive-only).
- Built-in methods for common operations (e.g.,
add(),remove(),contains()). - Type safety and performance optimizations.
2. Core Interfaces and Implementations
A. List Interface
Stores elements in an ordered sequence (allows duplicates). Common Implementations:
| Interface/Class | Description | Example Use Case |
|---|---|---|
ArrayList |
Resizable array (dynamic size) | Maintaining a list of orders (Daraz) |
LinkedList |
Doubly-linked list (fast insertions) | Transaction queue (eSewa) |
Vector |
Thread-safe ArrayList |
Legacy multi-threaded applications |
Visual: ArrayList vs. LinkedList
graph LR
A["ArrayList (Contiguous Memory)"] -->|"Add/Remove at End"| B["O(1)"]
A -->|"Add/Remove in Middle"| C["O(n)"]
D["LinkedList (Nodes with Pointers)"] -->|"Add/Remove at End"| E["O(1)"]
D -->|"Add/Remove in Middle"| F["O(1)"]B. Set Interface
Stores unique elements (no duplicates). Common Implementations:
| Class | Description | Example Use Case |
|---|---|---|
HashSet |
Uses hash table (no order) | Storing unique user IDs (Khalti) |
LinkedHashSet |
Maintains insertion order | Recently viewed items (YouTube) |
TreeSet |
Sorted elements (natural order) | Leaderboard (NEPSE stock prices) |
Visual: HashSet Insertion
C. Map Interface
Stores key-value pairs (no duplicate keys). Common Implementations:
| Class | Description | Example Use Case |
|---|---|---|
HashMap |
Fast lookup (unsorted) | Inventory mapping (Daraz) |
LinkedHashMap |
Maintains insertion order | Cache (browser history) |
TreeMap |
Sorted by keys | Phonebook (sorted by names) |
Visual: HashMap Operations
3. Generics: Type-Safe Programming
Generics allow classes/methods to operate on objects of any type while enforcing type safety at compile time.
Why Generics?
- Type Safety: Avoid
ClassCastExceptionby specifying types. - Code Reusability: Write once, use for any type (e.g.,
List<Integer>,List<String>). - Cleaner Code: No need for casts (e.g.,
(Integer) list.get(0)).
Syntax
// Generic class
class Box<T> {
private T content;
public void set(T content) { this.content = content; }
public T get() { return content; }
}
// Generic method
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
Autoboxing vs. Generics
| Feature | Autoboxing | Generics |
|---|---|---|
| Purpose | Converts primitives ↔ objects | Enforces type safety at compile time |
| Example | int → Integer |
List<String> (no primitives) |
| Works with Primitives? | Yes (int, double) |
No (only objects: Integer, Double) |
| Performance | Slight overhead | Zero overhead |
Worked Example: Generic Method for Sum
public class GenericSum {
public static <T extends Number> double sum(T[] numbers) {
double sum = 0;
for (T num : numbers) {
sum += num.doubleValue();
}
return sum;
}
public static void main(String[] args) {
Integer[] intNumbers = {1, 2, 3, 4, 5};
Double[] doubleNumbers = {1.1, 2.2, 3.3};
System.out.println("Sum of integers: " + sum(intNumbers)); // 15.0
System.out.println("Sum of doubles: " + sum(doubleNumbers)); // 6.6
}
}
Trace Table for sum(intNumbers):
| Step | numbers Array |
sum (double) |
Loop Iteration | num.doubleValue() |
sum Update |
|---|---|---|---|---|---|
| 1 | [1, 2, 3, 4, 5] |
0.0 | 1 | 1.0 | 1.0 |
| 2 | [1, 2, 3, 4, 5] |
1.0 | 2 | 2.0 | 3.0 |
| 3 | [1, 2, 3, 4, 5] |
3.0 | 3 | 3.0 | 6.0 |
| 4 | [1, 2, 3, 4, 5] |
6.0 | 4 | 4.0 | 10.0 |
| 5 | [1, 2, 3, 4, 5] |
10.0 | 5 | 5.0 | 15.0 |
4. Real-World Applications
A. eSewa: Transaction Queue (Queue Interface)
- Use Case: Processing payments in FIFO order.
- Implementation:
LinkedList(fast insertions/removals at both ends). - Why?:
- Ensures fairness (first transaction processed first).
- Thread-safe operations for concurrent users.
Visual: eSewa Transaction Queue
B. Daraz: Inventory Management (HashMap)
- Use Case: Mapping product IDs to stock quantities.
- Implementation:
HashMap<String, Integer>. - Why?:
- O(1) lookup time for product availability.
- Easy updates (e.g.,
map.put("Laptop101", 5)).
Visual: Daraz Inventory HashMap
C. NEPSE: Stock Price Leaderboard (TreeSet)
- Use Case: Displaying stocks sorted by price.
- Implementation:
TreeSet<Stock>(natural ordering by price). - Why?:
- Automatically sorted (no manual sorting needed).
- Efficient insertion/deletion (O(log n)).
5. Common Pitfalls and Best Practices
A. Autoboxing vs. Generics
- Mistake: Using generics with primitives (e.g.,
List<int>is invalid). - Fix: Use wrapper classes (
List<Integer>).
B. Type Erasure
- Generics are erased at runtime (e.g.,
List<String>andList<Integer>becomeList). - Implication: Cannot use primitives in generics (no
List<int>).
C. Wildcards (?)
- Upper Bounded:
List<? extends Number>(acceptsNumberor subclasses). - Lower Bounded:
List<? super Integer>(acceptsIntegeror superclasses likeNumber).
Example:
void printList(List<? extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
6. Exam Tip
What Examiners Look For
Definitions:
- Clearly define
List,Set,Map, and generics. - Example: "A
Setis a collection that does not allow duplicate elements."
- Clearly define
Code Examples:
- Write a generic class/method (e.g.,
Box<T>orsum()). - Include a trace table for algorithms (e.g.,
ArrayListinsertion).
- Write a generic class/method (e.g.,
Comparisons:
- Compare
ArrayListvs.LinkedList(time complexity for operations). - Compare
HashSetvs.TreeSet(ordering and performance).
- Compare
Real-World Scenarios:
- Relate to eSewa (Queue), Daraz (HashMap), or NEPSE (TreeSet).
- Example: "eSewa uses a
Queueto process transactions in FIFO order, ensuring fairness."
Autoboxing vs. Generics:
- Explain why
List<int>is invalid butList<Integer>works. - Example: "Generics enforce type safety at compile time, while autoboxing converts primitives to objects at runtime."
- Explain why
Sample Exam Questions and Answers
Q1: What is generic programming? Why is it needed? A: Generic programming allows classes/methods to operate on objects of any type while maintaining type safety. It is needed to:
- Avoid
ClassCastExceptionby specifying types at compile time. - Write reusable code (e.g., a
Box<T>class for any type). - Improve readability and maintainability.
Q2: Write a Java program to find whether the integer at even indices of an array is odd or not, and display the sum of those odd integers. A:
import java.util.ArrayList;
import java.util.List;
public class EvenIndexOddCheck {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
List<Integer> oddNumbers = new ArrayList<>();
int sum = 0;
for (int i = 0; i < numbers.length; i += 2) {
if (numbers[i] % 2 != 0) {
oddNumbers.add(numbers[i]);
sum += numbers[i];
}
}
System.out.println("Odd numbers at even indices: " + oddNumbers);
System.out.println("Sum of odd numbers: " + sum);
}
}
Output:
Odd numbers at even indices: [1, 3, 5, 7, 9]
Sum of odd numbers: 25
Q3: Why do we need generics? A: Generics are needed for:
- Type Safety: Prevents
ClassCastExceptionby enforcing types at compile time.- Example:
List<String>cannot store integers.
- Example:
- Code Reusability: Write a single method/class for multiple types.
- Example: A
Box<T>class for any object type.
- Example: A
- Cleaner Code: Eliminates the need for casts (e.g.,
(String) list.get(0)). - Performance: Avoids runtime type checks (unlike autoboxing).
7. Summary Table: Collections and Generics
| Concept | Description | Example | Time Complexity (Avg) |
|---|---|---|---|
ArrayList |
Resizable array | List<String> names |
O(1) add/remove end |
LinkedList |
Doubly-linked list | Queue<Integer> transactions |
O(1) add/remove both ends |
HashSet |
Unique elements (no order) | Set<String> userIDs |
O(1) add/contains |
TreeSet |
Sorted unique elements | Set<Double> stockPrices |
O(log n) add/contains |
HashMap |
Key-value pairs (no order) | Map<String, Integer> inventory |
O(1) get/put |
TreeMap |
Sorted key-value pairs | Map<String, String> phonebook |
O(log n) get/put |
| Generics | Type-safe classes/methods | class Box<T> |
N/A (compile-time check) |
8. Practice Problems
- Write a generic method to find the maximum element in an array of any type that implements
Comparable. - Compare
ArrayListandLinkedListwith a table showing time complexity foradd(),remove(), andget(). - Explain why
List<int>is invalid in Java, butList<Integer>is valid. - Write a program to simulate a bank transaction history using
List<Transaction>, whereTransactionis a class with fieldsamountanddate.
Based on the TU BITM syllabus for Object Oriented Programming With Java (IT234), unit 9.
Discussion
Loading…