Cosmic Module

J

Qubits of DPK

March 14, 2026

Core Java

Layman Explanation

Arrays are fixed-size boxes. Collections are expandable bags — they grow and shrink dynamically. Stream API is a conveyor belt that processes data in that bag without changing the original.

Collection Hierarchy

javascript
QUBITS OF DPK
1java.util.Collection
23├── List          → ordered, duplicates allowed
4│   ├── ArrayList   → dynamic array, fast access
5│   ├── LinkedList  → doubly linked list, fast insert/delete
6│   └── Vector      → thread-safe ArrayList (legacy)
78├── Set           → no duplicates
9│   ├── HashSet     → no order, fastest
10│   ├── LinkedHashSet → insertion order
11│   └── TreeSet     → sorted order
1213└── QueueFIFO
14    └── PriorityQueue → based on priority
15
16java.util.Map (not Collection)
17├── HashMap       → key-value, no order
18├── LinkedHashMap → insertion order
19├── TreeMap       → sorted by key
20└── Hashtable     → thread-safe HashMap (legacy)

ArrayList

java
QUBITS OF DPK
1ArrayList<String> names = new ArrayList<>();
2
3names.add("Deepak");
4names.add("Arjun");
5names.add("Priya");
6names.add(1, "Karthik");   // insert at index 1
7
8names.get(0);              // "Deepak"
9names.remove("Arjun");    // remove by value
10names.remove(1);           // remove by index
11names.size();              // count
12names.contains("Priya");  // true
13names.indexOf("Priya");   // index
14
15// Iterate
16for (String name : names) {
17    System.out.println(name);
18}
19
20// Sort
21Collections.sort(names);

ArrayList vs Array

javascript
QUBITS OF DPK
1Array:     fixed size, primitives OK, faster
2ArrayList: dynamic, Objects only, rich API

Set

java
QUBITS OF DPK
1HashSet<Integer> set = new HashSet<>();
2set.add(1); set.add(2); set.add(3);
3set.add(2);   // duplicate — silently ignored!
4
5System.out.println(set);       // [1, 2, 3] — no order guaranteed
6set.contains(2);               // true
7set.remove(1);
8set.size();                    // 2
9
10// LinkedHashSet — maintains insertion order
11LinkedHashSet<String> lhs = new LinkedHashSet<>();
12
13// TreeSet — sorted
14TreeSet<Integer> ts = new TreeSet<>();
15ts.add(3); ts.add(1); ts.add(2);
16System.out.println(ts);  // [1, 2, 3] always sorted

Map

java
QUBITS OF DPK
1HashMap<String, Integer> scores = new HashMap<>();
2scores.put("Deepak", 95);
3scores.put("Arjun", 88);
4scores.put("Priya", 92);
5scores.put("Deepak", 98);   // updates existing key
6
7scores.get("Deepak");        // 98
8scores.containsKey("Arjun"); // true
9scores.remove("Priya");
10scores.size();               // 2
11
12// Iterate map
13for (Map.Entry<String, Integer> entry : scores.entrySet()) {
14    System.out.println(entry.getKey() + ": " + entry.getValue());
15}
16
17// getOrDefault
18scores.getOrDefault("Unknown", 0);   // 0 if key missing

Comparator vs Comparable

Comparable (natural ordering)

java
QUBITS OF DPK
1class Student implements Comparable<Student> {
2    String name;
3    double cgpa;
4
5    @Override
6    public int compareTo(Student other) {
7        return Double.compare(this.cgpa, other.cgpa);  // sort by cgpa
8    }
9}
10
11List<Student> students = new ArrayList<>();
12Collections.sort(students);  // uses compareTo automatically

Comparator (custom ordering)

java
QUBITS OF DPK
1// Sort by name
2Collections.sort(students, (s1, s2) -> s1.name.compareTo(s2.name));
3
4// Sort by cgpa descending
5students.sort(Comparator.comparingDouble(Student::getCgpa).reversed());

Stream API

Process collections in a functional, pipeline style without modifying the original.
java
QUBITS OF DPK
1List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
2
3// filter — keep elements matching condition
4List<Integer> evens = numbers.stream()
5    .filter(n -> n % 2 == 0)
6    .collect(Collectors.toList());    // [2, 4, 6, 8, 10]
7
8// map — transform each element
9List<Integer> squares = numbers.stream()
10    .map(n -> n * n)
11    .collect(Collectors.toList());    // [1, 4, 9, 16, 25...]
12
13// reduce — combine to single value
14int sum = numbers.stream()
15    .reduce(0, Integer::sum);         // 55
16
17// sorted
18List<Integer> sorted = numbers.stream()
19    .sorted(Comparator.reverseOrder())
20    .collect(Collectors.toList());    // [10, 9, 8...]
21
22// forEach
23numbers.stream()
24    .filter(n -> n > 5)
25    .forEach(System.out::println);    // 6 7 8 9 10
26
27// count
28long count = numbers.stream()
29    .filter(n -> n % 2 == 0)
30    .count();                          // 5
31
32// Chained pipeline
33List<String> result = names.stream()
34    .filter(name -> name.startsWith("D"))
35    .map(String::toUpperCase)
36    .sorted()
37    .collect(Collectors.toList());

Collections Cheat Sheet

️ All Traps

java
QUBITS OF DPK
1// Trap 1 — ConcurrentModificationException
2for (String s : list) {
3    list.remove(s);   // ❌ can't modify while iterating!
4}
5// Fix: use Iterator or removeIf()
6list.removeIf(s -> s.startsWith("D"));  // ✅
7
8// Trap 2 — HashMap allows one null key
9map.put(null, "value");   // ✅ allowed
10Hashtable.put(null, "v"); // ❌ NullPointerException!
11
12// Trap 3 — Set uses equals() and hashCode()
13// If you add custom object to HashSet, must override both!
14
15// Trap 4 — Streams are lazy
16// Intermediate operations (filter, map) don't execute until terminal (collect, forEach)
17
18// Trap 5 — Streams can only be consumed ONCE
19Stream<Integer> stream = numbers.stream();
20stream.forEach(System.out::println);
21stream.count();   // ❌ IllegalStateException! Stream already consumed

Interview Answer (SDE-2)

"The Java Collections Framework provides dynamic data structures. List maintains order with duplicates (ArrayList for access, LinkedList for insertion). Set prevents duplicates (HashSet fastest, TreeSet sorted, LinkedHashSet ordered). Map stores key-value pairs (HashMap general use, TreeMap sorted, LinkedHashMap ordered). Stream API enables declarative data processing pipelines — lazy evaluation, intermediate ops (filter/map/sorted) and terminal ops (collect/reduce/forEach). Comparator for external sorting, Comparable for natural ordering. In production, prefer ConcurrentHashMap over HashMap for thread safety."

Interview Questions & MAANG-Level Answers

Q1. What is the difference between ArrayList and LinkedList?
ArrayList: backed by a dynamic array — O(1) random access by index, O(n) insert/delete at middle (shifting), cache-friendly, less memory overhead. LinkedList: doubly linked list — O(n) random access (traverse from head), O(1) insert/delete at head/tail if reference known, more memory (each node stores prev/next pointers). Use ArrayList for most cases (random access, iteration). Use LinkedList only for frequent insertions at ends (queue/deque operations).
Q2. What is the difference between HashSet, LinkedHashSet, and TreeSet?
HashSet: no ordering guarantee, O(1) add/remove/contains — fastest, uses HashMap internally. LinkedHashSet: maintains insertion order, O(1) operations, uses LinkedHashMap internally — use when order matters. TreeSet: sorted natural order (or custom Comparator), O(log n) operations, uses TreeMap internally — use when sorted iteration needed. All three reject duplicates using equals() and hashCode().
Q3. What is the difference between HashMap and Hashtable?
HashMap: not thread-safe, allows one null key and multiple null values, faster. Hashtable: thread-safe (all methods synchronized), no null keys or values, legacy class from Java 1.0. In modern Java, use ConcurrentHashMap instead of Hashtable for thread safety — it's much faster due to segment locking (not whole-table locking). HashMap is preferred for single-threaded code.
Q4. What is Comparable vs Comparator?
Comparable: implemented BY the class itself — defines natural ordering via compareTo(). The class "knows" how to compare itself. Comparator: external comparison logic — passed to sort methods. Allows multiple different orderings without modifying the class:
java
QUBITS OF DPK
1// Comparable — natural order by age
2class Student implements Comparable<Student> {
3    public int compareTo(Student other) { return this.age - other.age; }
4}
5// Comparator — external, sort by name
6students.sort(Comparator.comparing(Student::getName));
Use Comparable for the primary/natural ordering; Comparator for alternate orderings.
Q5. What is lazy evaluation in Streams?
Intermediate Stream operations (filter, map, sorted, distinct) are LAZY — they don't execute until a terminal operation (collect, forEach, reduce, count) is called. This enables optimization: if you filter + limit, Java stops after finding enough elements without processing the rest:
java
QUBITS OF DPK
1list.stream().filter(x -> x > 5).findFirst();  // stops at first match!
Short-circuiting operations (findFirst, anyMatch, limit) can terminate the pipeline early. This is why streams can efficiently process infinite data sources.
Q6. What is the difference between map() and flatMap()?
map(): transforms each element to exactly one output — 1-to-1 mapping. stream.map(x -> x * 2) — each element produces one result. flatMap(): transforms each element to zero or more outputs and flattens nested streams — 1-to-many:
java
QUBITS OF DPK
1// map: List<List<Integer>> -> Stream<List<Integer>>
2List<List<Integer>> nested = List.of(List.of(1,2), List.of(3,4));
3nested.stream().map(l -> l)  // Stream<List<Integer>>
4// flatMap: flattens to Stream<Integer>
5nested.stream().flatMap(Collection::stream)  // 1, 2, 3, 4
flatMap used for: splitting sentences into words, flattening nested collections, optional chaining.
Q7. Can you reuse a Stream? What happens if you try?
No. A Stream can only be consumed ONCE. After a terminal operation executes, the stream is closed. Trying to use it again throws IllegalStateException: stream has already been operated upon or closed. Always create a new stream from the source: list.stream() creates a fresh stream each time.
Q8. What is ConcurrentModificationException and how to avoid it?
Thrown when you structurally modify a collection while iterating it with a for-each loop or Iterator:
java
QUBITS OF DPK
1for (String s : list) { list.remove(s); }  // THROWS ConcurrentModificationException
Fixes: (1) Use Iterator.remove(): it.remove() during iteration. (2) list.removeIf(predicate) — cleanest. (3) Collect items to remove, then remove after loop. (4) Use CopyOnWriteArrayList for concurrent scenarios. The CME check is a fail-fast mechanism using a modCount counter.
Q9. How does HashMap handle hash collisions?
Collision: two keys produce the same bucket index. HashMap uses separate chaining: each bucket is a linked list of entries. On collision, new entry is appended to the list. Java 8 optimization: when a bucket's linked list exceeds 8 nodes, it converts to a Red-Black Tree — improving worst-case from O(n) to O(log n). When entries drop below 6, converts back to linked list.
Q10. What is the internal working of HashMap?
HashMap internally uses an Entry[] table (array of buckets). put(key, value): (1) Compute hash(key) — uses key's hashCode() then spreads bits. (2) Compute index: hash & (capacity-1). (3) If bucket empty, insert new Entry. (4) If bucket has entries, check for duplicate key via equals() — update if found, append if not. get(key): same hash computation — find bucket, traverse chain with equals() to find exact entry. Default capacity 16, load factor 0.75 — resizes (doubles) when 75% full, rehashing all entries.