Count Consonants in a String in Java
Problem
Consonants are every letter of the alphabet except a, e, i, o, and u.
Given a string, count how many consonants it contains.
Java Program
public class CountConsonants {
public static void main(String[] args) {
String str = "Programming";
String vowelSet = "aeiouAEIOU";
int count = 0;
for (char c : str.toCharArray()) {
// A letter that isn't a vowel is a consonant
if (Character.isLetter(c) && vowelSet.indexOf(c) == -1) count++;
}
System.out.println("Consonants: " + count);
}
}Output
Core Logic
A single pass through the string, keeping every letter that isn't a vowel, is the mirror image of counting vowels.
- 1
str.toCharArray()converts the string into achar[]so it can be scanned one character at a time. - 2
Character.isLetter(c)filters out spaces and punctuation, so only actual letters are considered. - 3
vowelSet.indexOf(c) == -1checks that the letter is NOT one of"aeiouAEIOU". - 4A letter passing both checks increments the
countvariable.
"Programming", the scan counts P, r, g, r, m, m, n, g as consonants — eight in total.Key Point: Character.isLetter(c) has to run first — without it, digits and punctuation would also pass the 'not a vowel' check and get miscounted as consonants.
Why: Each character is visited once, and only a single running counter is kept regardless of string length.
Key Concepts
Approach 2: Regex Replace
public class CountConsonantsRegex {
public static void main(String[] args) {
String str = "Programming";
// Removes vowels and non-letters, leaving only consonants behind
String consonantsOnly = str.replaceAll("(?i)[^bcdfghjklmnpqrstvwxyz]", "");
System.out.println("Consonants: " + consonantsOnly.length());
}
}
Output
Core Logic
A regex can strip out every vowel and non-letter in one call, leaving only the consonants behind to count.
- 1
str.replaceAll("(?i)[^bcdfghjklmnpqrstvwxyz]", "")matches anything that is NOT a consonant letter and removes it. - 2
(?i)makes the character class case-insensitive, so both uppercase and lowercase consonants are kept. - 3What's left is a new string containing only the consonants from the original.
- 4
.length()on that filtered string gives the total consonant count directly.
"Programming" leaves "Prgrmmng", whose length is 8.Key Point: The character class explicitly lists every consonant letter rather than excluding vowels, since regex character classes match single characters against a fixed set, not against a 'not one of these five' rule directly stated as vowels.
Why: replaceAll() builds an entirely new filtered string before length() can read its size.
Key Concepts
Approach 3: Java 8
public class CountConsonantsStream {
public static void main(String[] args) {
String str = "Programming";
String vowelSet = "aeiouAEIOU";
// Keeps only letters, then only the letters that aren't vowels
long count = str.chars()
.filter(Character::isLetter)
.filter(c -> vowelSet.indexOf(c) == -1)
.count();
System.out.println("Consonants: " + count);
}
}
Output
Core Logic
The same two-step filter — letters, then not-a-vowel — reads naturally as a chained stream pipeline.
- 1
str.chars()returns anIntStreamof the string's character codes. - 2
.filter(Character::isLetter)keeps only letters, dropping spaces and punctuation. - 3
.filter(c -> vowelSet.indexOf(c) == -1)keeps only the letters that aren't vowels. - 4
.count()reduces the twice-filtered stream down to a singlelongtotal.
"Programming" down to letters, then to non-vowels, leaves eight characters — the same consonants the loop version found.Key Point: Chaining two .filter() calls reads as 'letters, then non-vowels' in the same order the manual version's && condition checks them.
Why: The stream still visits every character once, and count() reduces straight down to a single long without collecting anything.