Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java collection exercises: counters, duplicates, and stable output

Last updated: 28 Sept 20263 min read
tutorial
IntermediateBy AITrove Editorial

A collection exercise defines input, identity, ordering, and output rules before choosing a container or writing a loop.

Java 8+. Use a JDK that supports this release.

Task 1: count receipt states

Given paid, pending, paid, declined, pending, produce the count for each state in first-seen order. Use a map whose encounter order is part of its contract. Empty input must produce an empty map, and this task rejects null or blank states.

Write the loop before reading the answer. A successful solution should not rely on HashMap happening to print in the desired order. Test repeated values separated by other values, not only consecutive duplicates.

Task 2: detect duplicates without losing the rule

Return the number of events beyond the first occurrence of each receipt ID. The IDs r-8, r-9, r-8, r-8 should yield two duplicates. A set records membership; it does not keep an event count unless you track that count separately.

Decide whether IDs are case-sensitive and whether whitespace is meaningful. This solution uses exact String equality. Normalization must be an explicit upstream rule, not a side effect introduced to make a test pass.

Task 3: reason about the collection choice

Explain why a LinkedList scanned by repeated indexed get can cost quadratic traversal. Explain why a PriorityQueue’s iterator does not give sorted output. These questions test operation contracts, not the ability to recite container names.

The complete answer below solves the first two tasks. Extend it with empty inputs, all-distinct inputs, and a rejected null value. The LinkedList exercise set covers endpoint behavior separately.

Working program

Java
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ReceiptCollectionTasks {
    static Map<String, Integer> counts(List<String> states) {
        Map<String, Integer> result = new LinkedHashMap<>();
        for (String state : states) {
            if (state == null || state.trim().isEmpty()) throw new IllegalArgumentException("State required");
            result.merge(state, 1, Integer::sum);
        }
        return result;
    }
    static int duplicates(List<String> ids) {
        Set<String> seen = new HashSet<>();
        int duplicates = 0;
        for (String id : ids) {
            if (id == null) throw new IllegalArgumentException("ID required");
            if (!seen.add(id)) duplicates++;
        }
        return duplicates;
    }
    public static void main(String[] args) {
        System.out.println(counts(Arrays.asList("paid", "pending", "paid", "declined", "pending")));
        System.out.println(duplicates(Arrays.asList("r-8", "r-9", "r-8", "r-8")));
    }
}

Output

Output
{paid=2, pending=2, declined=1}
2

Cost and design choices

Each task requires expected O(n) work for bounded-length, well-distributed String keys. The map or set stores O(k) distinct keys. Hashing and equality costs still depend on text length.

The duplicate count is process-local and bounded by the input list. It is not a durable exactly-once guarantee for external payments. A production ingestion path needs a separate persistence contract.

Common Mistakes

  • Do not let accidental map iteration order satisfy the requirement.
  • Do not confuse duplicate IDs with distinct duplicated keys.
  • Do not mutate collection keys after insertion.
java
collections-exercises
Storage details