Count Vowels and Consonants in a String in Java
Problem
Vowels are the letters a, e, i, o, and u; every other letter is a consonant.
Given a string, count how many vowels and how many consonants it contains.
Java Program
public class VowelConsonantCount {
public static void main(String[] args) {
String str = "Java Programming";
int vowels = 0, consonants = 0;
String vowelSet = "aeiouAEIOU";
// Scan each character once
for (char c : str.toCharArray()) {
if (Character.isLetter(c)) { // skip spaces and punctuation
if (vowelSet.indexOf(c) != -1) vowels++; // found in the vowel set
else consonants++; // any other letter is a consonant
}
}
System.out.println("Vowels: " + vowels + ", Consonants: " + consonants);
}
}Output
Core Logic
One pass through the string is enough — check each letter against a small set of vowels and bucket it accordingly.
- 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 counted. - 3For each letter,
vowelSet.indexOf(c)checks whether it appears in"aeiouAEIOU". - 4A match increments the
vowelscounter; anything else incrementsconsonants. - 5After the loop, both counters hold the final vowel and consonant totals.
"Java Programming", the scan finds 5 vowels and 10 consonants.Key Point: Including both cases in vowelSet (aeiouAEIOU) avoids a separate call to toLowerCase() for every character.
Why: Each character is visited once, and only the two running counters are kept regardless of string length.
Key Concepts
Approach 2: Java Streams
public class VowelConsonantCountStream {
public static void main(String[] args) {
String str = "Java Programming";
String vowelSet = "aeiouAEIOU";
// Count letters that appear in the vowel set
long vowels = str.chars()
.filter(Character::isLetter)
.filter(c -> vowelSet.indexOf(c) != -1)
.count();
// Count letters that don't appear in the vowel set
long consonants = str.chars()
.filter(Character::isLetter)
.filter(c -> vowelSet.indexOf(c) == -1)
.count();
System.out.println("Vowels: " + vowels + ", Consonants: " + consonants);
}
}
Output
Core Logic
The same classification can be expressed as a stream pipeline instead of a loop — filter for letters, then split into vowels and consonants.
- 1
str.chars()returns anIntStreamof the string's character codes. - 2
.filter(Character::isLetter)keeps only letters, dropping spaces and punctuation, just like the manual version's check. - 3A second
.filter()splits the stream into vowels (found invowelSet) or consonants (not found). - 4
.count()reduces each filtered stream down to a singlelongtotal.
"Java Programming" twice — once for vowels, once for consonants — produces 5 and 10 respectively.Key Point: This runs the string through two separate stream pipelines, so for very large strings the single-pass loop is actually more efficient — the stream version trades a bit of performance for readability.
Why: Each filter-and-count pipeline still scans every character once, and count() reduces straight down to a single long without collecting anything.
Key Concepts
Interview Questions
Why check Character.isLetter before testing for a vowel?
Without it, spaces, digits and punctuation would fall into the "not a vowel" branch and be counted as consonants. "Java Programming" would report 11 consonants instead of 10 because of the space.
How do you count vowels and consonants with a stream?
Filter the letters first, then partition them: str.chars().filter(Character::isLetter).mapToObj(c -> (char) c).collect(Collectors.partitioningBy(c -> "aeiouAEIOU".indexOf(c) >= 0, Collectors.counting())) gives both counts in one map.