Find Least Frequent Character in a String in Java
Problem
The least frequent character is whichever character has the lowest count once every character's occurrences have been tallied.
Given a string, find the character that appears the fewest times, along with its count.
Java Program
import java.util.LinkedHashMap;
import java.util.Map;
public class LeastFrequentCharacter {
public static void main(String[] args) {
String str = "success";
Map<Character, Integer> freq = new LinkedHashMap<>();
for (char c : str.toCharArray()) {
freq.put(c, freq.getOrDefault(c, 0) + 1); // increment this character's running count
}
Character minChar = null;
int minCount = Integer.MAX_VALUE;
for (Map.Entry<Character, Integer> entry : freq.entrySet()) {
if (entry.getValue() < minCount) { // found a new lowest count so far
minChar = entry.getKey();
minCount = entry.getValue();
}
}
System.out.println("Least frequent character: " + minChar + " (" + minCount + " time)");
}
}Output
Core Logic
Building the frequency map first, then scanning it once for the lowest count, is the mirror image of finding the most frequent character.
- 1A
LinkedHashMap<Character, Integer>namedfreqtracks each character's count, exactly like counting character frequency. - 2
freq.getOrDefault(c, 0)reads the current count, or0if unseen, thenfreq.put(c, ...)stores the incremented count. - 3
minCharandminCountstart at the first entry's character and count, then walk the rest ofentrySet(). - 4Whenever an entry's count is lower than
minCount, bothminCharandminCountare updated to that entry.
"success", 'u' and 'e' both appear once — the fewest of any character — and 'u' wins since it's encountered first.Key Point: Starting minCount from the first entry, rather than from a sentinel like Integer.MAX_VALUE, guarantees a valid character is always reported, even for a string with only one distinct character.
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
Approach 2: Java 8
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class LeastFrequentCharacterStream {
public static void main(String[] args) {
String str = "success";
Map<Character, Long> freq = str.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()));
// Compares every entry by its count and keeps the smallest one
Map.Entry<Character, Long> minEntry = freq.entrySet().stream()
.min(Map.Entry.comparingByValue())
.orElseThrow();
System.out.println("Least frequent character: " + minEntry.getKey() + " (" + minEntry.getValue() + " time)");
}
}
Output
Core Logic
Once the frequency map exists, a stream can find its lowest-valued entry directly instead of a manual running-minimum loop.
- 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().min(Map.Entry.comparingByValue())compares every entry by its count and keeps the single smallest one. - 4
.orElseThrow()unwraps the result from theOptionalit's wrapped in.
"success" produces counts for each character, and min() picks out 'u': 1 as the smallest entry, matching the manual version's first-seen tiebreak.Key Point: Using LinkedHashMap::new as the map factory keeps ties resolved the same way as the manual loop — min() keeps the first minimum it encounters while scanning entries in insertion order.
Why: groupingBy() still visits every character once to build the map, and min() then makes one pass over its entries to find the smallest.