Java Syntax for DSA

Quick revision of the collections you use in every problem⏱ 24 min readUpdated

The Java arrays, strings and collections syntax you type in every coding round, with compiled snippets and the Big-O of each operation.

0 of 54 done

In an interview you want to spend your thinking on the algorithm, not on whether it is length or size(), or how to write a max-heap. This sheet collects the Java syntax that shows up in almost every DSA problem, grouped by data structure, with the time complexity of each operation.

Skim it before a coding round. Every snippet compiles and can be opened in the site's editor to run and tweak; tick an item once you can write it from memory, and read the bullets — they are the gotchas interviewers notice.

Arrays

Fixed-size, zero-indexed, fastest random access.

  1. 1Declare & initialise (1D / 2D)

    Sizes are fixed at creation and elements start at their default value.

    • arr.length is a field (no parentheses); Strings use length(), lists use size().
    • Defaults: 0 for numbers, false for boolean, '\u0000' for char, null for objects.
    java
    int[] a = new int[5];            // [0, 0, 0, 0, 0]
    int[] b = {3, 1, 2};             // array literal
    int[][] grid = new int[3][4];    // 3 rows x 4 cols, all 0
    int[][] g2 = {{1, 2}, {3, 4}};
    String[] names = new String[2];  // [null, null]
    boolean[] seen = new boolean[4]; // all false
    System.out.println(b.length + " " + grid.length + " " + grid[0].length); // 3 3 4
    
  2. 2Iterate: index loop & for-each

    Use the index loop when you need i; for-each when you only need values.

    • Assigning to x inside for-each does NOT change the array.
    java
    int[] nums = {4, 5, 6};
    for (int i = 0; i < nums.length; i++) System.out.print(nums[i] + " "); // 4 5 6
    for (int x : nums) System.out.print(x + " ");                          // 4 5 6
    int[][] grid = {{1, 2}, {3, 4}};
    for (int[] row : grid)
        for (int v : row) System.out.print(v + " ");                       // 1 2 3 4
    
  3. 3Arrays.fill

    Sets every slot to one value, e.g. infinity for distances or -1 for memo tables.

    • Arrays.fill only works on one dimension; loop over the rows of a 2D array.
    java
    int[] dist = new int[4];
    Arrays.fill(dist, Integer.MAX_VALUE);
    int[][] memo = new int[3][3];
    for (int[] row : memo) Arrays.fill(row, -1);  // fill row by row
    System.out.println(Arrays.toString(memo[0])); // [-1, -1, -1]
    
  4. 4Arrays.sort

    Sorts in place in ascending order; an optional range sorts [from, to).

    • Descending order needs a boxed Integer[]; int[] takes no comparator.
    • For int[] descending: sort ascending, then read it backwards.
    java
    int[] a = {5, 2, 9, 1};
    Arrays.sort(a);                                 // [1, 2, 5, 9]
    int[] b = {9, 7, 3, 1};
    Arrays.sort(b, 1, 3);                           // [9, 3, 7, 1] (only indices 1..2)
    Integer[] boxed = {5, 2, 9, 1};
    Arrays.sort(boxed, Collections.reverseOrder()); // [9, 5, 2, 1]
    
  5. 5Sort int[][] by a column

    Pass a comparator to order rows, e.g. intervals by start time.

    • Break ties with a second key: x[0] != y[0] ? Integer.compare(x[0], y[0]) : Integer.compare(x[1], y[1]).
    java
    int[][] intervals = {{5, 6}, {1, 3}, {2, 4}};
    Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0])); // by start
    // same: Arrays.sort(intervals, Comparator.comparingInt(x -> x[0]));
    System.out.println(Arrays.deepToString(intervals)); // [[1, 3], [2, 4], [5, 6]]
    
    Practice: Merge Intervals →
  6. 6Arrays.toString / deepToString

    Printing an array directly shows a type@hash, not its contents.

    • Compare contents with Arrays.equals(a, b); a == b compares references.
    java
    int[] a = {1, 2, 3};
    System.out.println(a);                      // e.g. [I@6d06d69c (not the contents!)
    System.out.println(Arrays.toString(a));     // [1, 2, 3]
    int[][] g = {{1, 2}, {3, 4}};
    System.out.println(Arrays.deepToString(g)); // [[1, 2], [3, 4]]
    
  7. 7Copying: copyOfRange, copyOf, clone

    Create a real copy; plain assignment only copies the reference.

    • clone() on a 2D array is shallow: the rows are still shared.
    java
    int[] a = {1, 2, 3, 4, 5};
    int[] part = Arrays.copyOfRange(a, 1, 4); // [2, 3, 4] (end exclusive)
    int[] bigger = Arrays.copyOf(a, 7);       // [1, 2, 3, 4, 5, 0, 0]
    int[] copy = a.clone();                   // independent copy
    int[] alias = a;                          // SAME array, not a copy
    alias[0] = 99;                            // a[0] is now 99, copy[0] is still 1
    
OperationCodeTime
Access / updatea[i], a[i] = xO(1)
Linear searchloopO(n)
Binary search (sorted)Arrays.binarySearch(a, x)O(log n)
Sort primitivesArrays.sort(int[])O(n log n)
Sort objects (stable)Arrays.sort(T[], cmp)O(n log n)
FillArrays.fill(a, v)O(n)
Copy rangeArrays.copyOfRange(a, i, j)O(j - i)

Strings & StringBuilder

Strings are immutable; build new text with StringBuilder.

  1. 8length, charAt, toCharArray

    Read characters by index, or copy to a char[] when you need to sort or edit.

    java
    String s = "hello";
    int n = s.length();             // 5 (a method, unlike array.length)
    char c = s.charAt(1);           // 'e'
    char[] cs = s.toCharArray();    // mutable copy
    Arrays.sort(cs);
    String sorted = new String(cs); // "ehllo"
    
  2. 9substring & indexOf

    Extract part of a string; the end index is exclusive.

    • substring copies characters, so it costs O(length) — not free inside a loop.
    java
    String s = "interview";
    String a = s.substring(0, 5);   // "inter" (begin inclusive, end exclusive)
    String b = s.substring(5);      // "view"  (to the end)
    int at = s.indexOf("view");     // 5 (-1 if absent)
    boolean has = s.contains("tv"); // false
    
  3. 10equals vs ==, compareTo

    Compare string contents with equals; == only checks if both are the same object.

    • compareTo returns negative / 0 / positive — never rely on it being exactly -1 or 1.
    java
    String a = "abc", b = new String("abc");
    System.out.println(a == b);                          // false (different objects)
    System.out.println(a.equals(b));                     // true  (same characters)
    System.out.println(a.equalsIgnoreCase("ABC"));       // true
    System.out.println("apple".compareTo("banana") < 0); // true (lexicographic)
    
  4. 11split, join, valueOf, parseInt

    Convert between strings, pieces and numbers.

    • split takes a regex: split on a dot with "\\.", on a pipe with "\\|".
    java
    String[] parts = "a,b,,c".split(",");                 // [a, b, , c]
    String[] words = "  hi   there ".trim().split("\\s+"); // [hi, there]
    String joined = String.join("-", words);              // "hi-there"
    String num = String.valueOf(42);                      // "42"
    int back = Integer.parseInt("42");                    // 42
    
  5. 12char arithmetic

    Characters are numbers, so c - 'a' maps 'a'..'z' to 0..25.

    • A 26-slot array beats a HashMap for lowercase-letter counts.
    java
    String s = "leetcode";
    int[] freq = new int[26];
    for (char c : s.toCharArray()) freq[c - 'a']++;
    System.out.println(freq['e' - 'a']); // 3
    char next = (char) ('a' + 2);        // 'c' (cast back to char)
    int digit = '7' - '0';               // 7
    
    Pattern: Hashing →
  6. 13Character helpers

    Static checks and conversions on single characters.

    • Handy for 'valid palindrome' style problems that skip punctuation.
    java
    char c = 'B';
    boolean d = Character.isDigit('5');          // true
    boolean l = Character.isLetter(c);           // true
    boolean ld = Character.isLetterOrDigit('_'); // false
    boolean up = Character.isUpperCase(c);       // true
    char lower = Character.toLowerCase(c);       // 'b'
    
  7. 14StringBuilder

    A mutable character buffer; most methods return the builder so calls can chain.

    • Use sb.length() and sb.charAt(i) just like a String.
    • Backtracking: undo an append with sb.deleteCharAt(sb.length() - 1).
    java
    StringBuilder sb = new StringBuilder("abc");
    sb.append('d').append(12);        // "abcd12"
    sb.insert(0, "x");                // "xabcd12"
    sb.deleteCharAt(sb.length() - 1); // "xabcd1"
    sb.setCharAt(0, 'X');             // "Xabcd1"
    sb.reverse();                     // "1dcbaX"
    String out = sb.toString();
    
  8. 15Why += in a loop is O(n^2)

    Each += copies the whole string into a new one; StringBuilder appends in place.

    java
    String slow = "";
    for (int i = 0; i < 1000; i++) slow += i;    // copies every time: O(n^2)
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 1000; i++) sb.append(i); // amortised O(1) per append
    String fast = sb.toString();
    System.out.println(slow.equals(fast));       // true, same result
    
OperationCodeTime
Read a chars.charAt(i)O(1)
Substrings.substring(i, j)O(j - i)
Compares.equals(t), s.compareTo(t)O(n)
Searchs.indexOf(t), s.contains(t)O(n·m) worst
Appendsb.append(x)O(1) amortised
Insert / delete at frontsb.insert(0, x), sb.deleteCharAt(0)O(n)
Reversesb.reverse()O(n)

HashMap

Key -> value lookups in O(1) average time.

  1. 16put, get, getOrDefault, containsKey, remove

    The core map API; get returns null for missing keys.

    • int x = map.get(missingKey) throws NullPointerException (unboxing null).
    • Compare Integer values from two maps with .equals, not == (caching only covers -128..127).
    java
    Map<String, Integer> age = new HashMap<>();
    age.put("ana", 30);
    age.put("ana", 31);                    // overwrites -> 31
    int a = age.get("ana");                // 31
    Integer missing = age.get("bob");      // null
    int safe = age.getOrDefault("bob", 0); // 0
    boolean has = age.containsKey("ana");  // true
    age.remove("ana");
    System.out.println(age.size());        // 0
    
  2. 17Counting with merge

    merge(k, 1, Integer::sum) inserts 1 or adds 1 to the existing count.

    • Decrement and drop at zero: if (count.merge(c, -1, Integer::sum) == 0) count.remove(c);
    java
    String s = "banana";
    Map<Character, Integer> count = new HashMap<>();
    for (char c : s.toCharArray()) count.merge(c, 1, Integer::sum);
    System.out.println(count); // {a=3, b=1, n=2}
    // same thing: count.put(c, count.getOrDefault(c, 0) + 1);
    
    Practice: Two Sum →
  3. 18Grouping with computeIfAbsent

    Create the bucket list on first use, then add to it, in one line.

    • Also the standard way to build an adjacency list: graph.computeIfAbsent(u, x -> new ArrayList<>()).add(v).
    java
    String[] words = {"eat", "tea", "tan", "ate"};
    Map<String, List<String>> groups = new HashMap<>();
    for (String w : words) {
        char[] k = w.toCharArray();
        Arrays.sort(k);
        groups.computeIfAbsent(new String(k), x -> new ArrayList<>()).add(w);
    }
    System.out.println(groups.get("aet")); // [eat, tea, ate]
    
    Practice: Group Anagrams →
  4. 19Iterate entrySet / keySet / values

    Use entrySet when you need both key and value.

    • HashMap order is unspecified: use LinkedHashMap for insertion order, TreeMap for sorted keys.
    • Calling m.remove inside a for-each loop throws ConcurrentModificationException.
    java
    Map<String, Integer> m = new HashMap<>(Map.of("x", 1, "y", 2));
    for (Map.Entry<String, Integer> e : m.entrySet())
        System.out.println(e.getKey() + "=" + e.getValue());
    for (String k : m.keySet()) System.out.print(k + " ");
    for (int v : m.values()) System.out.print(v + " ");
    m.entrySet().removeIf(e -> e.getValue() < 2); // safe removal while iterating
    
OperationCodeTime
Insert / updatemap.put(k, v)O(1) avg
Search by keymap.get(k), containsKey(k)O(1) avg
Deletemap.remove(k)O(1) avg
Count / groupmerge, computeIfAbsentO(1) avg
Search by valuemap.containsValue(v)O(n)
IterateentrySet / keySet / valuesO(n)

HashSet

Unique values with O(1) average membership checks.

  1. 20add, contains, remove, size

    add returns false when the value is already present.

    • Use if (!set.add(x)) to detect a duplicate in one call.
    java
    Set<Integer> seen = new HashSet<>();
    System.out.println(seen.add(5)); // true  (newly added)
    System.out.println(seen.add(5)); // false (already present)
    boolean has = seen.contains(5);  // true
    seen.remove(5);
    System.out.println(seen.size()); // 0
    
    Practice: Contains Duplicate →
  2. 21Build from a collection & iterate

    Copying a list into a set removes duplicates.

    • Set.of("a", "a") throws IllegalArgumentException on duplicates and is immutable.
    • Need a sorted or insertion-ordered set? Use TreeSet or LinkedHashSet.
    java
    List<String> raw = List.of("a", "b", "a");
    Set<String> s = new HashSet<>(raw);
    System.out.println(s.size());                 // 2
    for (String x : s) System.out.print(x + " "); // order not guaranteed
    
  3. 22Set operations: retainAll / addAll / removeAll

    Intersection, union and difference — copy first because these mutate the set.

    java
    Set<Integer> a = new HashSet<>(List.of(1, 2, 3));
    Set<Integer> b = new HashSet<>(List.of(2, 3, 4));
    Set<Integer> inter = new HashSet<>(a); inter.retainAll(b); // [2, 3]
    Set<Integer> union = new HashSet<>(a); union.addAll(b);    // [1, 2, 3, 4]
    Set<Integer> diff = new HashSet<>(a); diff.removeAll(b);   // [1]
    System.out.println(inter + " " + union + " " + diff);
    
OperationCodeTime
Insertset.add(x)O(1) avg
Membershipset.contains(x)O(1) avg
Deleteset.remove(x)O(1) avg
Intersection / unionretainAll / addAllO(n + m) avg

ArrayList & List

Growable array; the default list in Java.

  1. 23add, add(i, x), get, set, size, contains

    Program to the List interface and use ArrayList underneath.

    java
    List<Integer> list = new ArrayList<>();
    list.add(10); list.add(20);    // [10, 20]
    list.add(0, 5);                // [5, 10, 20] (shifts the rest right)
    int first = list.get(0);       // 5
    list.set(1, 99);               // [5, 99, 20]
    System.out.println(list.size() + " " + list.contains(20)); // 3 true
    
  2. 24remove(index) vs remove(value)

    With List<Integer>, remove(1) removes index 1, not the value 1.

    • remove(Object) deletes only the first match.
    java
    List<Integer> list = new ArrayList<>(List.of(10, 20, 30));
    list.remove(1);                   // removes INDEX 1 -> [10, 30]
    list.remove(Integer.valueOf(10)); // removes VALUE 10 -> [30]
    System.out.println(list);         // [30]
    
  3. 25Sorting a list

    Sort in place ascending or with any comparator.

    java
    List<Integer> list = new ArrayList<>(List.of(3, 1, 2));
    Collections.sort(list);                // [1, 2, 3]
    list.sort(Collections.reverseOrder()); // [3, 2, 1]
    list.sort(null);                       // natural order again: [1, 2, 3]
    System.out.println(list);              // [1, 2, 3]
    
  4. 26List.of is immutable

    List.of gives a fixed list; wrap it in new ArrayList<>(...) to modify.

    • Backtracking bug: adding path itself instead of new ArrayList<>(path) leaves you with empty lists.
    • List.of also rejects null elements.
    java
    List<Integer> fixed = List.of(1, 2, 3);
    // fixed.add(4);  -> UnsupportedOperationException at runtime
    List<Integer> copy = new ArrayList<>(fixed); // mutable copy
    copy.add(4);                                 // [1, 2, 3, 4]
    List<List<Integer>> res = new ArrayList<>();
    res.add(new ArrayList<>(copy));              // snapshot, not a live reference
    
    Pattern: Backtracking →
  5. 27Convert int[] <-> List<Integer>

    Primitive arrays need boxing; a plain loop is always fine.

    • Arrays.asList(intArray) gives a List<int[]> of size 1 — not what you want.
    java
    int[] arr = {3, 1, 2};
    List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
    int[] back = list.stream().mapToInt(Integer::intValue).toArray();
    List<Integer> viaLoop = new ArrayList<>();
    for (int x : arr) viaLoop.add(x);
    System.out.println(list + " " + Arrays.toString(back)); // [3, 1, 2] [3, 1, 2]
    
OperationCodeTime
Read / write by indexget(i), set(i, x)O(1)
Appendadd(x)O(1) amortised
Insert / remove in middleadd(i, x), remove(i)O(n)
Remove lastremove(list.size() - 1)O(1)
Searchcontains(x), indexOf(x)O(n)
SortCollections.sort / list.sortO(n log n)

PriorityQueue (Heap)

Always hands you the smallest (or largest) element fast.

  1. 28Min-heap (default)

    With no comparator, the smallest element is at the head.

    • Printing or iterating a heap does NOT give sorted order; only poll() does.
    • peek() / poll() return null on an empty heap.
    java
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    minHeap.offer(5); minHeap.offer(1); minHeap.offer(3);
    System.out.println(minHeap.peek());    // 1 (smallest, not removed)
    System.out.println(minHeap.poll());    // 1 (removed)
    System.out.println(minHeap.size());    // 2
    System.out.println(minHeap.isEmpty()); // false
    
  2. 29Max-heap

    Reverse the ordering with Collections.reverseOrder() or a comparator.

    • (a, b) -> b - a also works but can overflow for large/negative values; prefer Integer.compare(b, a).
    java
    PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
    // equivalent: new PriorityQueue<>((a, b) -> Integer.compare(b, a));
    maxHeap.addAll(List.of(5, 1, 3));
    System.out.println(maxHeap.poll()); // 5
    System.out.println(maxHeap.poll()); // 3
    
  3. 30Heap of int[] pairs

    Order arrays by one of their fields, e.g. {node, dist} for Dijkstra.

    java
    // MIN-heap of {node, dist}: smallest dist comes out first
    PriorityQueue<int[]> pq = new PriorityQueue<>((x, y) -> Integer.compare(x[1], y[1]));
    pq.offer(new int[]{0, 7});
    pq.offer(new int[]{1, 2});
    int[] top = pq.poll();
    System.out.println(top[0] + " " + top[1]); // 1 2
    
    Pattern: Shortest path →
  4. 31Heap of Map.Entry ordered by value

    Put map entries in a heap to pull keys by their counts.

    • Swap x and y to flip min <-> max; label your heap in a comment so you don't mix them up.
    java
    Map<String, Integer> freq = Map.of("a", 5, "b", 2, "c", 9);
    // MAX-heap by value: highest count comes out first
    PriorityQueue<Map.Entry<String, Integer>> maxByCount =
        new PriorityQueue<>((x, y) -> Integer.compare(y.getValue(), x.getValue()));
    maxByCount.addAll(freq.entrySet());
    System.out.println(maxByCount.poll().getKey()); // c
    // MIN-heap by value: (x, y) -> Integer.compare(x.getValue(), y.getValue())
    
    Practice: Top K Frequent Elements →
  5. 32Top-k with a size-k min-heap

    Keep only k items; the head is then the k-th largest.

    • O(n log k) time and O(k) space, better than sorting when k is small.
    java
    int[] nums = {4, 1, 7, 3, 9, 2};
    int k = 3;
    PriorityQueue<Integer> heap = new PriorityQueue<>(); // min-heap
    for (int x : nums) {
        heap.offer(x);
        if (heap.size() > k) heap.poll(); // evict the smallest
    }
    System.out.println(heap.peek()); // 4 (3rd largest)
    
    Pattern: Heap / Top-K →
OperationCodeTime
Insertpq.offer(x)O(log n)
Remove min/maxpq.poll()O(log n)
Read min/maxpq.peek()O(1)
Size / emptypq.size(), pq.isEmpty()O(1)
Remove arbitrary / containspq.remove(x), pq.contains(x)O(n)
Build from collectionnew PriorityQueue<>(list)O(n)

Queue & Deque

FIFO queues for BFS; double-ended queues for stacks and windows.

  1. 33Queue: offer, poll, peek

    First in, first out — the backbone of BFS.

    • poll() / peek() return null when empty; remove() / element() throw instead.
    • ArrayDeque does not allow null elements; LinkedList does.
    java
    Queue<Integer> q = new ArrayDeque<>(); // or new LinkedList<>()
    q.offer(1); q.offer(2); q.offer(3);
    System.out.println(q.peek()); // 1 (front, not removed)
    System.out.println(q.poll()); // 1 (removed)
    System.out.println(q.size()); // 2
    
    Pattern: Graph BFS →
  2. 34Deque as a stack

    push, pop and peek all work on the front of an ArrayDeque.

    • Preferred over java.util.Stack: not synchronized, faster, and the Java docs recommend it.
    java
    Deque<Integer> stack = new ArrayDeque<>();
    stack.push(1); stack.push(2); stack.push(3);
    System.out.println(stack.peek()); // 3 (top)
    System.out.println(stack.pop());  // 3
    System.out.println(stack);        // [2, 1] (top first)
    
  3. 35Both ends: offerFirst / offerLast / pollFirst / pollLast

    Add, read or remove at either end in O(1).

    java
    Deque<Integer> dq = new ArrayDeque<>();
    dq.offerLast(2); dq.offerLast(3); // [2, 3]
    dq.offerFirst(1);                 // [1, 2, 3]
    System.out.println(dq.peekFirst() + " " + dq.peekLast()); // 1 3
    dq.pollFirst();                   // [2, 3]
    dq.pollLast();                    // [2]
    System.out.println(dq);           // [2]
    
  4. 36Sliding window maximum (monotonic deque)

    Keep indices whose values decrease; the front is the window max.

    • Each index is added and removed at most once, so the whole pass is O(n).
    java
    int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
    int k = 3;
    Deque<Integer> dq = new ArrayDeque<>(); // indices, values decreasing
    List<Integer> out = new ArrayList<>();
    for (int i = 0; i < nums.length; i++) {
        if (!dq.isEmpty() && dq.peekFirst() <= i - k) dq.pollFirst(); // out of window
        while (!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]) dq.pollLast();
        dq.offerLast(i);
        if (i >= k - 1) out.add(nums[dq.peekFirst()]);
    }
    System.out.println(out); // [3, 3, 5, 5, 6, 7]
    
    Practice: Sliding Window Maximum →
OperationCodeTime
Enqueue / dequeueoffer(x), poll()O(1)
Front of queuepeek()O(1)
Push / pop (stack)push(x), pop(), peek()O(1)
Either endofferFirst/Last, pollFirst/Last, peekFirst/LastO(1)
Searchcontains(x)O(n)

Stack

Last in, first out — know the legacy class, use Deque.

  1. 37Legacy java.util.Stack

    Still common in older code and interview answers; the API is push/pop/peek/isEmpty.

    • Stack extends Vector: every call is synchronized and it exposes index methods that break LIFO.
    • pop() / peek() on an empty Stack throw EmptyStackException.
    java
    Stack<Integer> st = new Stack<>();
    st.push(1); st.push(2);
    System.out.println(st.peek());    // 2
    System.out.println(st.pop());     // 2
    System.out.println(st.isEmpty()); // false
    System.out.println(st);           // [1] (printed bottom first)
    
  2. 38Recommended: Deque<> stack = new ArrayDeque<>()

    Same push/pop/peek calls, faster and cleaner — use it in interviews.

    • On ArrayDeque, pop() on empty throws NoSuchElementException; poll() / peek() return null.
    java
    String s = "({[]})";
    Deque<Character> st = new ArrayDeque<>();
    boolean ok = true;
    for (char c : s.toCharArray()) {
        if (c == '(' || c == '[' || c == '{') st.push(c);
        else if (st.isEmpty() || "([{".indexOf(st.pop()) != ")]}".indexOf(c)) { ok = false; break; }
    }
    ok = ok && st.isEmpty();
    System.out.println(ok); // true
    
    Practice: Valid Parentheses →

LinkedList & custom nodes

Hand-rolled nodes for list/tree problems, plus the built-in LinkedList.

  1. 39ListNode + dummy head

    A dummy node before the head removes special cases when building or deleting.

    • Return dummy.next, never dummy.
    • Always null-check p.next before reading p.next.next.
    java
    class ListNode {
        int val; ListNode next;
        ListNode(int val) { this.val = val; }
    }
    ListNode dummy = new ListNode(0), tail = dummy;
    for (int v : new int[]{1, 2, 3}) { tail.next = new ListNode(v); tail = tail.next; }
    ListNode head = dummy.next; // 1 -> 2 -> 3
    for (ListNode p = head; p != null; p = p.next) System.out.print(p.val + " "); // 1 2 3
    
    Pattern: Linked list →
  2. 40TreeNode definition

    The standard binary-tree node used by almost every tree problem.

    • In a full program declare it as a static class (LeetCode already provides it).
    java
    class TreeNode {
        int val; TreeNode left, right;
        TreeNode(int val) { this.val = val; }
    }
    TreeNode root = new TreeNode(2);
    root.left = new TreeNode(1);
    root.right = new TreeNode(3);
    System.out.println(root.left.val + " " + root.val + " " + root.right.val); // 1 2 3
    
    Pattern: Tree DFS →
  3. 41java.util.LinkedList API

    A doubly linked list that is also a List and a Deque.

    • get(i) walks the list: O(n). Prefer ArrayList for index access, ArrayDeque for queues.
    java
    LinkedList<Integer> ll = new LinkedList<>();
    ll.add(2); ll.addFirst(1); ll.addLast(3);               // [1, 2, 3]
    System.out.println(ll.getFirst() + " " + ll.getLast()); // 1 3
    ll.removeFirst();                                       // [2, 3]
    ll.removeLast();                                        // [2]
    System.out.println(ll);                                 // [2]
    
OperationCodeTime
Add / remove at endsaddFirst, addLast, removeFirst, removeLastO(1)
Read endsgetFirst(), getLast()O(1)
Access by indexget(i)O(n)
Searchcontains(x)O(n)

TreeMap & TreeSet

Sorted keys plus floor/ceiling lookups in O(log n).

  1. 42TreeMap: ordered keys, floorKey, ceilingKey

    Keys stay sorted; floor/ceiling find the nearest key below or above a value.

    • lowerKey / higherKey are the strict (< / >) versions.
    • Results can be null — use Integer, not int, to hold them.
    java
    TreeMap<Integer, String> tm = new TreeMap<>();
    tm.put(30, "c"); tm.put(10, "a"); tm.put(20, "b");
    System.out.println(tm);                                 // {10=a, 20=b, 30=c}
    System.out.println(tm.firstKey() + " " + tm.lastKey()); // 10 30
    System.out.println(tm.floorKey(25));                    // 20 (largest key <= 25)
    System.out.println(tm.ceilingKey(25));                  // 30 (smallest key >= 25)
    System.out.println(tm.floorKey(5));                     // null (none)
    
  2. 43headMap, tailMap, pollFirstEntry

    Range views and removing the smallest entry.

    • Views are live: changes to them write through to the map.
    java
    TreeMap<Integer, String> tm = new TreeMap<>(Map.of(10, "a", 20, "b", 30, "c"));
    System.out.println(tm.headMap(20));       // {10=a} (keys < 20)
    System.out.println(tm.headMap(20, true)); // {10=a, 20=b} (keys <= 20)
    System.out.println(tm.tailMap(20));       // {20=b, 30=c} (keys >= 20)
    System.out.println(tm.pollFirstEntry());  // 10=a (and removes it)
    System.out.println(tm);                   // {20=b, 30=c}
    
  3. 44TreeSet

    A sorted set with the same nearest-value queries.

    • Use a TreeMap<value, count> when you need a sorted multiset (duplicates).
    java
    TreeSet<Integer> ts = new TreeSet<>(List.of(5, 1, 9, 3));
    System.out.println(ts);             // [1, 3, 5, 9]
    System.out.println(ts.floor(4));    // 3
    System.out.println(ts.ceiling(4));  // 5
    System.out.println(ts.higher(5));   // 9 (strictly greater)
    System.out.println(ts.pollFirst()); // 1 (removes the smallest)
    System.out.println(ts.last());      // 9
    
OperationCodeTime
Insert / delete / lookupput, remove, get, containsKeyO(log n)
Nearest keyfloorKey, ceilingKey, lowerKey, higherKeyO(log n)
Smallest / largestfirstKey, lastKey, first, lastO(log n)
Remove smallestpollFirstEntry, pollFirstO(log n)
Range viewheadMap, tailMap, subMapO(log n) to create
Iterate in orderfor-eachO(n)

Sorting & comparators

Describe the order once, reuse it for sort, heaps and TreeMaps.

  1. 45comparingInt, thenComparing, reversed

    Build multi-key orderings declaratively, e.g. on a record.

    • .reversed() flips the WHOLE chain built so far.
    • With lambdas, chaining may need a typed parameter: Comparator.comparingInt((int[] a) -> a[0]).reversed().
    java
    record Person(String name, int age) {}
    List<Person> ps = new ArrayList<>(List.of(
        new Person("Cy", 30), new Person("Al", 25), new Person("Bo", 30)));
    ps.sort(Comparator.comparingInt(Person::age).thenComparing(Person::name));
    System.out.println(ps.get(0).name() + ps.get(1).name() + ps.get(2).name()); // AlBoCy
    ps.sort(Comparator.comparingInt(Person::age).reversed());
    System.out.println(ps.get(0).age()); // 30
    
  2. 46Lambda comparators

    Return negative if a goes first, positive if b goes first, 0 if tied.

    • Object sorts are stable (TimSort): equal elements keep their original order.
    java
    String[] words = {"pear", "fig", "banana", "kiwi"};
    // shorter first; ties alphabetical
    Arrays.sort(words, (a, b) -> a.length() != b.length()
            ? Integer.compare(a.length(), b.length())
            : a.compareTo(b));
    System.out.println(Arrays.toString(words)); // [fig, kiwi, pear, banana]
    
  3. 47Integer.compare vs subtraction

    Subtracting ints can overflow and invert the order; Integer.compare never does.

    • Use Long.compare for longs and Double.compare for doubles.
    java
    int a = Integer.MAX_VALUE, b = -1;
    System.out.println(a - b);                 // -2147483648: overflow claims a < b!
    System.out.println(Integer.compare(a, b)); // 1: correct, a > b
    Comparator<Integer> asc = Integer::compare;
    Comparator<Integer> desc = (x, y) -> Integer.compare(y, x);
    
  4. 48Natural, reverse and case-insensitive order

    Ready-made comparators for common orderings.

    • Collections.reverseOrder() and Comparator.reverseOrder() give the same ordering — both need the ().
    java
    List<String> names = new ArrayList<>(List.of("bob", "Al", "cy"));
    names.sort(Comparator.naturalOrder());     // [Al, bob, cy] (uppercase sorts first)
    names.sort(Comparator.reverseOrder());     // [cy, bob, Al]
    names.sort(String.CASE_INSENSITIVE_ORDER); // [Al, bob, cy]
    System.out.println(names);                 // [Al, bob, cy]
    

Handy utilities

Math, overflow guards, parsing and bit tricks you reach for constantly.

  1. 49Math helpers, limits & long overflow

    Know the int limits and widen to long before multiplying big values.

    • Math.pow returns a double; avoid it for exact integer powers.
    • Math.abs(Integer.MIN_VALUE) is still negative.
    • Use Math.floorMod(x, m) to get a non-negative remainder for negative x.
    java
    int a = Math.max(3, 7), b = Math.min(3, 7), c = Math.abs(-4); // 7 3 4
    int best = Integer.MIN_VALUE;     // -2147483648: start value for a max search
    int lowest = Integer.MAX_VALUE;   //  2147483647: start value for a min search
    long ok = (long) 100000 * 100000; // 10000000000 (cast BEFORE multiplying)
    int bad = 100000 * 100000;        // 1410065408 (silently overflowed)
    System.out.println(ok + " " + bad);
    
  2. 50Safe midpoint

    lo + (hi - lo) / 2 or (lo + hi) >>> 1 avoid overflow in binary search.

    java
    int lo = 2_000_000_000, hi = 2_100_000_000;
    int wrong = (lo + hi) / 2;     // -97483648 (lo + hi overflowed)
    int mid1 = lo + (hi - lo) / 2; // 2050000000
    int mid2 = (lo + hi) >>> 1;    // 2050000000 (unsigned shift)
    System.out.println(wrong + " " + mid1 + " " + mid2);
    
    Pattern: Binary search →
  3. 51Parsing & number <-> string

    Convert text to numbers and back, including other bases.

    • parseInt throws NumberFormatException on bad input such as "" or "12a".
    java
    int n = Integer.parseInt("-123");         // -123
    long big = Long.parseLong("9000000000");  // too big for int
    String s = Integer.toString(255);         // "255"
    String bin = Integer.toBinaryString(5);   // "101"
    int fromBin = Integer.parseInt("101", 2); // 5
    char d = (char) ('0' + 7);                // '7'
    
  4. 52Collections.swap / reverse / frequency / max

    Static helpers that work on any List.

    java
    List<Integer> list = new ArrayList<>(List.of(1, 2, 3, 2));
    Collections.swap(list, 0, 3);               // [2, 2, 3, 1]
    Collections.reverse(list);                  // [1, 3, 2, 2]
    int twos = Collections.frequency(list, 2);  // 2
    int mx = Collections.max(list), mn = Collections.min(list); // 3 1
    System.out.println(list + " " + twos + " " + mx + " " + mn); // [1, 3, 2, 2] 2 3 1
    
  5. 53Arrays.asList caveat

    Returns a fixed-size view backed by the array, not a normal ArrayList.

    java
    String[] arr = {"b", "a"};
    List<String> view = Arrays.asList(arr); // fixed-size, backed by arr
    view.set(0, "z");                       // arr[0] is now "z" too
    // view.add("c");  -> UnsupportedOperationException
    List<String> real = new ArrayList<>(Arrays.asList(arr)); // fully mutable
    int[] prim = {1, 2};
    System.out.println(Arrays.asList(prim).size()); // 1 (a List<int[]>!)
    
  6. 54Bit tricks

    Constant-time checks on the binary form of an int.

    • x ^ x == 0 and x ^ 0 == x: XOR all numbers to find the one without a pair.
    • Use >>> for an unsigned right shift of negative numbers.
    java
    int n = 12;                                 // binary 1100
    boolean odd = (n & 1) == 1;                 // false
    int dropLow = n & (n - 1);                  // 8 (1000): clears the lowest set bit
    boolean pow2 = n > 0 && (n & (n - 1)) == 0; // false
    int ones = Integer.bitCount(n);             // 2
    int lowBit = n & -n;                        // 4: isolates the lowest set bit
    int half = n >> 1, dbl = n << 1;            // 6, 24
    

Quick tips

  • Declare with interfaces (List, Map, Set, Deque, Queue) and pick the implementation on the right-hand side.
  • Reach for ArrayDeque for both stacks and queues; mention why if you skip Stack.
  • Use Integer.compare (never a - b) in comparators, and cast to long before multiplying large ints.
  • Compare objects (Strings, Integers) with .equals, never ==.
  • Say the complexity of each collection call out loud — interviewers listen for O(1) avg vs O(log n) vs O(n).

Inspired by a public Java Syntax Notes revision handout; rewritten, corrected and compile-tested.