Find First Non-Repeated Character Using HashMap in Java
Problem
Tallying every character's total count in a HashMap first, then re-scanning the original string in order, finds the first character whose count never rose above one.
Given a string, use a HashMap to find the first character, reading left to right, that appears exactly once.
Java Program
import java.util.HashMap;
import java.util.Map;
public class FirstUniqueCharHashMap {
public static void main(String[] args) {
String text = "minimum";
Map<Character, Integer> tally = new HashMap<>();
for (char c : text.toCharArray()) {
tally.put(c, tally.getOrDefault(c, 0) + 1);
}
char result = '\0';
for (char c : text.toCharArray()) {
if (tally.get(c) == 1) {
result = c;
break; // first character whose total count is exactly one
}
}
System.out.println("First non-repeated character: " + result);
}
}Output
Core Logic
Counting every character's total frequency in one pass, then walking the original string in a second pass, finds the first character whose final tally is exactly one.
- 1A
HashMap<Character, Integer>namedtallyrecords each character's total count across the whole string. - 2
tally.getOrDefault(c, 0)reads the running count, defaulting to0on first appearance, andput()stores it back incremented. - 3A second loop walks the original string's characters in their original left-to-right order — not the map's, which has no guaranteed order.
- 4The first character whose
tally.get(c)equals1is the answer, reported immediately withbreak.
"minimum", 'm' ends with a total count of 3 and 'i' with 2, so both are skipped even though they come first — the next character, 'n', has a total count of 1 and is reported.Key Point: The second loop has to re-scan the original string, not the map — a plain HashMap doesn't remember which key was encountered first in the source text, only what each one's final count ended up being.
Why: The first pass builds a tally 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
public class FirstUniqueCharStream {
public static void main(String[] args) {
String text = "minimum";
// A character with no repeats has the same first and last position in the string
char result = text.chars()
.mapToObj(c -> (char) c)
.filter(c -> text.indexOf(c) == text.lastIndexOf(c))
.findFirst()
.orElse('\0');
System.out.println("First non-repeated character: " + result);
}
}
Output
Core Logic
Comparing each character's first and last position in the string sidesteps the tally map entirely — a character with no repeats has the same index both times.
- 1
text.chars().mapToObj(c -> (char) c)streams the string's characters in their original left-to-right order. - 2
.filter(c -> text.indexOf(c) == text.lastIndexOf(c))keeps only characters whose first occurrence and last occurrence are the same position — true only when the character appears exactly once. - 3
.findFirst()stops at the first character satisfying that condition, which is also the first non-repeated character overall since the stream preserves original order. - 4
.orElse('\0')supplies a fallback in case every character repeats.
"minimum", 'm' and 'i' each have different first/last positions, so they're filtered out; 'n' is the first character where both positions match, and it's found.Key Point: No explicit tally map is built at all here — the trade-off is that indexOf()/lastIndexOf() each rescan the string, making this pipeline less efficient than the two-pass HashMap version despite reading more compactly.
Why: Each of the n characters triggers an indexOf() and lastIndexOf() call, each of which can scan up to n characters, unlike the primary approach's single O(n) tally pass.