Java ProgramsStringsFind Duplicate Characters in a String

Find Duplicate Characters in a String in Java

intermediate·  Strings  ·  String

Problem

A duplicate character is one that appears two or more times in a string, as opposed to a character that appears exactly once.

Given a string, find every character that appears more than once.

Input
programming
Output
Duplicate characters: r, g, m

Java Program

Java
import java.util.LinkedHashMap; import java.util.Map; public class FindDuplicateCharacters { public static void main(String[] args) { String str = "programming"; Map<Character, Integer> freq = new LinkedHashMap<>(); for (char c : str.toCharArray()) { freq.put(c, freq.getOrDefault(c, 0) + 1); // reads the current count, or 0 if unseen, then increments it } StringBuilder duplicates = new StringBuilder(); for (Map.Entry<Character, Integer> entry : freq.entrySet()) { if (entry.getValue() > 1) { // only keep characters whose count is more than one if (duplicates.length() > 0) duplicates.append(", "); duplicates.append(entry.getKey()); } } System.out.println("Duplicate characters: " + duplicates); } }

Output

Duplicate characters: r, g, m

Core Logic

Building a full frequency map first, then keeping only the entries with a count greater than one, separates 'how often' from 'which ones repeat'.

How It Works
  1. 1A LinkedHashMap<Character, Integer> named freq tracks each character's count, exactly like counting character frequency.
  2. 2freq.getOrDefault(c, 0) reads the current count, or 0 if unseen, then freq.put(c, ...) stores the incremented count.
  3. 3After the full scan, entrySet() is walked once more, checking entry.getValue() > 1 for each character.
  4. 4Every character whose count exceeds one is appended to the result, in the order it was first seen.
In "programming", 'p', 'o', 'a', 'i', and 'n' each appear once, while 'r', 'g', and 'm' each appear twice — so the duplicates reported are r, g, m.
💡

Key Point: This is the same frequency map used to count character occurrences — finding duplicates is just a filter applied on top of it.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Building the frequency map visits every character once and holds one entry per distinct character, up to n in the worst case.

Key Concepts

LinkedHashMapgetOrDefault()entrySet()

Approach 2: Java 8

Java
import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; public class FindDuplicateCharactersStream { public static void main(String[] args) { String str = "programming"; Map<Character, Long> freq = str.chars() .mapToObj(c -> (char) c) .collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting())); // Keeps only the characters whose count is greater than one String duplicates = freq.entrySet().stream() .filter(e -> e.getValue() > 1) .map(Map.Entry::getKey) .map(String::valueOf) .collect(Collectors.joining(", ")); System.out.println("Duplicate characters: " + duplicates); } }

Output

Duplicate characters: r, g, m

Core Logic

groupingBy plus counting() builds the same frequency map declaratively, and a stream filter keeps only the entries with a count above one.

How It Works
  1. 1str.chars().mapToObj(c -> (char) c) turns the string's character codes into a Stream<Character>.
  2. 2Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()) groups equal characters and counts each group, in first-appearance order.
  3. 3freq.entrySet().stream().filter(e -> e.getValue() > 1) keeps only the entries whose count is greater than one.
  4. 4.map(Map.Entry::getKey) pulls just the character out of each surviving entry, and Collectors.joining(", ") joins them into the final result.
Grouping "programming" and filtering for counts above one keeps r, g, and m, the same duplicates the manual version found.
💡

Key Point: The filter condition — count > 1 — is the exact same rule the manual version's second loop checks, just expressed as a stream predicate instead of an if statement.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: groupingBy() still visits every character once while building the map, which holds one entry per distinct character just like the manual version.

Key Concepts

StreamCollectors.groupingBy()Collectors.counting()

Related Programs