Find First Non-Repeated Character in a String in Java
Problem
A non-repeated character is one that appears exactly once in a string, as opposed to a character with two or more occurrences.
Given a string, find the first character, reading left to right, that appears exactly once.
Java Program
import java.util.HashMap;
import java.util.Map;
public class FirstNonRepeatedCharacter {
public static void main(String[] args) {
String str = "swiss";
Map<Character, Integer> freq = new HashMap<>();
for (char c : str.toCharArray()) {
freq.put(c, freq.getOrDefault(c, 0) + 1);
}
char result = '\0';
for (char c : str.toCharArray()) {
if (freq.get(c) == 1) {
result = c;
break; // first character with a total count of exactly one
}
}
System.out.println("First non-repeated character: " + result);
}
}Output
Core Logic
Counting every character's total frequency first, then scanning the original string in order, finds the first character whose count never rose above one.
- 1A
HashMap<Character, Integer>namedfreqtracks each character's total count across the whole string. - 2
freq.getOrDefault(c, 0)reads the current count, or0if unseen, thenfreq.put(c, ...)stores the incremented count. - 3A second loop walks the original string's characters in their original order, not the map's.
- 4The first character whose
freq.get(c)equals1is the answer, printed immediately withbreak.
"swiss", 's' has a total count of 3, so it's skipped even though it's first — the next character, 'w', has a count of 1 and is reported.Key Point: The second loop has to walk the original string, not the frequency map — a map alone doesn't remember which character came first in the source text.
Why: The first pass builds a frequency map holding one entry per distinct character, and the second pass re-scans the string looking up each character's count.
Key Concepts
Approach 2: Java 8
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class FirstNonRepeatedCharacterStream {
public static void main(String[] args) {
String str = "swiss";
Map<Character, Long> freq = str.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()));
// Keeps only count-1 entries, then takes the first — which is first-appearance order
char result = freq.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst()
.orElseThrow();
System.out.println("First non-repeated character: " + result);
}
}
Output
Core Logic
Building the frequency map with insertion order preserved lets a single filtered stream find the answer directly, without a second scan of the original string.
- 1
str.chars().mapToObj(c -> (char) c)turns the string's character codes into aStream<Character>. - 2
Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting())groups equal characters and counts each group, in first-appearance order. - 3
freq.entrySet().stream().filter(e -> e.getValue() == 1)keeps only the entries whose count is exactly one. - 4
.findFirst()returns the first surviving entry — which is also the first one encountered in the original string, since the map preserves that order.
"swiss" in first-appearance order gives s: 3, w: 1, i: 1; filtering for count 1 and taking the first result gives 'w'.Key Point: Using LinkedHashMap::new as the map factory is what lets a single pass over the map substitute for the manual version's second scan of the original string.
Why: groupingBy() still visits every character once to build the map, and filtering plus findFirst() then makes one more pass over its entries.