Find Last Non-Repeated Character in a String in Java
Problem
A non-repeated character is one that appears exactly once in a string — the last one is whichever such character sits closest to the end.
Given a string, find the last character, reading right to left, that appears exactly once.
Java Program
import java.util.HashMap;
import java.util.Map;
public class LastNonRepeatedCharacter {
public static void main(String[] args) {
String str = "programming";
Map<Character, Integer> freq = new HashMap<>();
for (char c : str.toCharArray()) {
freq.put(c, freq.getOrDefault(c, 0) + 1);
}
char result = '\0';
for (int i = str.length() - 1; i >= 0; i--) {
char c = str.charAt(i);
if (freq.get(c) == 1) {
result = c;
break; // first non-repeated character found scanning from the end
}
}
System.out.println("Last non-repeated character: " + result);
}
}Output
Core Logic
Counting every character's total frequency first, then scanning the string backward, finds the last position holding a character that never repeats.
- 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 string backward, from index
str.length() - 1down to0. - 4The first character encountered in that backward walk whose
freq.get(c)equals1is the answer, printed immediately withbreak.
"programming", the last character 'g' has a count of 2, so the scan continues backward until it reaches 'n', which has a count of 1.Key Point: This is the mirror image of finding the last repeated character — same reverse scan, just the opposite condition on the count.
Why: The first pass builds a frequency map holding one entry per distinct character, and the second pass re-scans the string backward looking up each character's count.
Key Concepts
Approach 2: Java 8
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class LastNonRepeatedCharacterStream {
public static void main(String[] args) {
String str = "programming";
Map<Character, Long> freq = str.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()));
// Walks the string's indices in reverse, stopping at the first non-repeated character
char result = IntStream.range(0, str.length())
.map(i -> str.length() - 1 - i)
.mapToObj(str::charAt)
.filter(c -> freq.get(c) == 1)
.findFirst()
.orElseThrow();
System.out.println("Last non-repeated character: " + result);
}
}
Output
Core Logic
The same reversed-index stream used to find the last repeated character works here too — just flip the filter condition.
- 1
str.chars().mapToObj(c -> (char) c)andCollectors.groupingBy()build the frequency map exactly like the manual version. - 2
IntStream.range(0, str.length()).map(i -> str.length() - 1 - i)generates the string's indices in reverse order. - 3
.mapToObj(str::charAt)converts each reversed index into its character. - 4
.filter(c -> freq.get(c) == 1).findFirst()keeps only non-repeated characters and takes the first one found in this backward order.
"programming"'s indices in reverse visits 'g' first (count 2, skipped), then 'n' (count 1, matched).Key Point: Only the filter's comparison changes from the last-repeated-character version — == 1 instead of > 1 — everything else about the pipeline stays the same.
Why: groupingBy() still visits every character once to build the map, and the reversed-index stream then makes one more pass looking for the first non-repeated character.