Skip to content
SDETRole
SDETRole

Java interview question

Using Java streams, find the duplicate values in a list and count their occurrences.

intermediate 2–5 yrs #streams#collections#coding-exercise#collectors

Short answer

Group with Collectors.groupingBy(Function.identity(), Collectors.counting()) and keep entries with a count above one. For just the duplicate values, add to a HashSet and collect elements whose add returns false. Explain complexity, ordering (LinkedHashMap) and when a plain loop is clearer.

Answer

This is a common live-coding warm-up. The idiomatic stream answer groups elements by themselves and counts them, then keeps the groups with a count greater than one. It runs in linear time, O(n), with O(n) extra space.

Count every duplicate

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Duplicates {
    public static void main(String[] args) {
        List<String> emails = List.of(
            "a@x.com", "b@x.com", "a@x.com", "c@x.com", "b@x.com", "a@x.com");

        Map<String, Long> duplicates = emails.stream()
            .collect(Collectors.groupingBy(
                Function.identity(),
                LinkedHashMap::new,          // keep first-seen order
                Collectors.counting()))
            .entrySet().stream()
            .filter(e -> e.getValue() > 1)
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (x, y) -> x,
                LinkedHashMap::new));

        System.out.println(duplicates); // {a@x.com=3, b@x.com=2}
    }
}

The two-argument groupingBy(Function.identity(), Collectors.counting()) returns a HashMap with no guaranteed order. Passing LinkedHashMap::new makes the output deterministic, which matters if you assert on it. Use TreeMap::new for sorted output.

Just the duplicate values

A Set.add call returns false if the element was already present:

Set<String> seen = new HashSet<>();
Set<String> dups = emails.stream()
    .filter(e -> !seen.add(e))
    .collect(Collectors.toCollection(LinkedHashSet::new));
// [a@x.com, b@x.com]

This is concise, but it relies on a side effect inside a lambda, which is only safe for sequential streams. With .parallel() the shared HashSet is not thread-safe. Some interviewers will probe this; the groupingBy version has no such issue.

A plain loop is also a good answer

Map<String, Integer> counts = new LinkedHashMap<>();
for (String e : emails) {
    counts.merge(e, 1, Integer::sum);
}
counts.values().removeIf(c -> c < 2);

Being able to say “the loop is just as fast and arguably easier to read” shows judgement rather than stream fixation.

Custom objects

For a list of objects, either group by a key (groupingBy(User::email, counting())) or make sure the class implements equals and hashCode correctly. A record does this automatically. Without it, every element is unique by identity and you find no duplicates.

Normalisation

Real-world duplicate checks usually need normalisation first, for example .map(s -> s.trim().toLowerCase(Locale.ROOT)) for emails. Mention it: it shows you think about the data, not just the algorithm.

Where this shows up in testing

  • Asserting that an API returns no duplicate IDs: assertEquals(ids.size(), new HashSet<>(ids).size()), with the groupingBy result in the failure message so you can see which IDs repeat.
  • Checking test data generators produce unique emails.

What interviewers look for

  • A working groupingBy plus counting solution and a filter on count.
  • Awareness of ordering and the LinkedHashMap overload.
  • Complexity stated correctly.
  • Understanding of side effects in parallel streams and the role of equals/hashCode.

A strong answer covers

  • Uses groupingBy with counting
  • Filters entries with count greater than one
  • Alternative using a Set where add() returns false
  • Discusses complexity and ordering
  • Relies on correct equals/hashCode for custom objects
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →