Explain the Java Collections Framework hierarchy.
Collectionbranches intoList(ordered, duplicates allowed:ArrayList),Set(no duplicates:HashSet,TreeSet) andQueue/Deque(ArrayDeque,PriorityQueue).Map(HashMap,TreeMap) stores key-value pairs and does not extendCollection.The legacy
Vector,StackandHashtableare replaced byArrayList,ArrayDequeandHashMap.What is the difference between an array and an ArrayList in Java?
An array has a fixed length and can hold primitives; an
ArrayListgrows but holds only objects, sointvalues are boxed.Javaimport java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { int[] arr = {3, 1, 2}; List<Integer> list = new ArrayList<>(List.of(3, 1, 2)); list.add(4); // an array cannot grow Arrays.sort(arr); list.sort(null); System.out.println(Arrays.toString(arr) + " length " + arr.length); System.out.println(list + " size " + list.size()); } }It prints
[1, 2, 3] length 3and[1, 2, 3, 4] size 4. In OpenJDK a fullArrayListcopies itself into an array about 1.5 times bigger; the spec only promises that appending is O(1) amortized. See ArrayList.What is the difference between ArrayList and LinkedList?
ArrayListis a resizable array with O(1)get(i);LinkedListis a doubly linked list with O(n)get(i)and two pointers per node. UseArrayListby default.Inserting in the middle is O(n) for both, because the linked list must first walk to the position, and arrays are far more cache friendly. For queues and stacks use
ArrayDeque.What does
list.remove(1)do on aList<Integer>?Javaimport java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> list = new ArrayList<>(List.of(1, 2, 3)); list.remove(1); System.out.println(list); } }It prints
[1, 3].List<Integer>hasremove(int index)andremove(Object o), and the literal1is anint, so the call removes index 1, the value 2.To remove the value 1, write
list.remove(Integer.valueOf(1)).How does HashMap work internally in Java?
A
HashMapis an array of buckets.putspreadshashCode()(h ^ (h >>> 16)), picks buckethash & (capacity - 1)and chains colliding entries; lookups walk the chain withequals().The table (16 buckets by default) doubles when it passes 75% full. Since Java 8 a chain longer than 8 becomes a red-black tree once the table has 64 buckets (a smaller table resizes instead). One
nullkey is allowed, in bucket 0. See the hash map visualization.Practice it: Two Sum, Group Anagrams
What is the difference between HashMap, Hashtable and ConcurrentHashMap?
HashMapis not thread safe and allows onenullkey.Hashtablelocks the whole table on every method and is legacy.ConcurrentHashMapreads without locks and locks single bins on writes; it allows nonulls, and its iterators never throwConcurrentModificationException.Use its atomic
mergeorcompute: agetfollowed by aputis still a race.How does HashSet work internally?
A
HashSetis aHashMapwhose keys are the elements and whose values are one shared dummy object;addreturns false when the key already exists.So it has O(1) average
addandcontains, no order, and needs consistentequals()andhashCode().LinkedHashSetkeeps insertion order,TreeSetsorted order.Practice it: Contains Duplicate, Intersection of Two Arrays
How many equal objects does a
HashSetkeep: plain classes vs records?Javaimport java.util.HashSet; import java.util.Set; class PointClass { int x, y; PointClass(int x, int y) { this.x = x; this.y = y; } } record PointRecord(int x, int y) {} public class Main { public static void main(String[] args) { Set<PointClass> a = new HashSet<>(); a.add(new PointClass(1, 2)); a.add(new PointClass(1, 2)); Set<PointRecord> b = new HashSet<>(); b.add(new PointRecord(1, 2)); b.add(new PointRecord(1, 2)); System.out.println(a.size() + " " + b.size()); } }It prints
2 1.PointClasskeepsObject's identity-basedequals()andhashCode(), so both objects stay in the set. Arecordgenerates both from its components, so the secondaddis a duplicate.What is the difference between HashMap, LinkedHashMap and TreeMap?
Iteration order:
HashMapguarantees none,LinkedHashMapkeeps insertion order, andTreeMapkeeps keys sorted.Javaimport java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.TreeMap; public class Main { public static void main(String[] args) { String[] keys = {"banana", "apple", "cherry"}; Map<String, Integer> hash = new HashMap<>(); Map<String, Integer> linked = new LinkedHashMap<>(); Map<String, Integer> tree = new TreeMap<>(); for (String k : keys) { hash.put(k, k.length()); linked.put(k, k.length()); tree.put(k, k.length()); } System.out.println("linked: " + linked.keySet()); System.out.println("tree: " + tree.keySet()); System.out.println("hash has " + hash.size() + " keys, order not guaranteed"); } }linkedprints[banana, apple, cherry]andtreeprints[apple, banana, cherry].TreeMapcosts O(log n) instead of O(1), but addsfloorKey()and range views.What is a fail-fast iterator? How do you remove elements while iterating?
A fail-fast iterator throws
ConcurrentModificationExceptionwhen the collection changes structurally other than through the iterator; it checks amodCountcounter on eachnext(). It detects bugs and gives no thread safety. Remove withremoveIforIterator.remove():Javaimport java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> a = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6)); a.removeIf(n -> n % 2 == 0); System.out.println(a); List<Integer> b = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6)); Iterator<Integer> it = b.iterator(); while (it.hasNext()) { if (it.next() > 3) it.remove(); } System.out.println(b); } }It prints
[1, 3, 5]and[1, 2, 3]. Concurrent collections have weakly consistent iterators that never throw.What happens when you remove an element inside a for-each loop?
Javaimport java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> list = new ArrayList<>(List.of(1, 2, 3)); for (Integer x : list) { if (x == 2) list.remove(x); } System.out.println(list); } }It prints
[1, 3]with no exception. After removing 2, the size and the iterator's cursor are both 2, sohasNext()is false and themodCountcheck innext()never runs.Removing 1 or 3 throws
ConcurrentModificationException, so a passing test proves nothing here; useremoveIf.What is the difference between Comparable and Comparator?
Comparableis a class's own natural order (compareTo); aComparatoris an external order, so one class can have many.Javaimport java.util.ArrayList; import java.util.Comparator; import java.util.List; record Student(String name, int marks) implements Comparable<Student> { @Override public int compareTo(Student other) { return name.compareTo(other.name); // natural order: by name } } public class Main { public static void main(String[] args) { List<Student> list = new ArrayList<>(List.of( new Student("Ravi", 82), new Student("Anu", 91), new Student("Kiran", 82))); list.sort(null); // natural order System.out.println(list.stream().map(Student::name).toList()); list.sort(Comparator.comparingInt(Student::marks).reversed() .thenComparing(Student::name)); System.out.println(list.stream().map(Student::name).toList()); } }It prints
[Anu, Kiran, Ravi]twice: Anu has the top mark and the two 82s tie-break by name. Avoida - bcomparators, which can overflow; useInteger.compare.Practice it: Merge Intervals
Java Collections Interview Questions
How HashMap, ArrayList and the other collections work inside, and which one to pick.
12 questions