Count Vowels 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 it contains.
Java Program
public class CountVowels {
public static void main(String[] args) {
String str = "Programming";
String vowelSet = "aeiouAEIOU";
int count = 0;
// Scan each character once, checking membership in the vowel set
for (char c : str.toCharArray()) {
if (vowelSet.indexOf(c) != -1) count++;
}
System.out.println("Vowels: " + count);
}
}Output
Core Logic
A single pass through the string, checking each letter against a small set of vowels, is all it takes.
- 1
str.toCharArray()converts the string into achar[]so it can be scanned one character at a time. - 2
vowelSet.indexOf(c)checks whether the current character appears in"aeiouAEIOU". - 3A match increments the
countvariable; anything else is skipped. - 4After the loop,
countholds the total number of vowels found.
"Programming", the scan finds 'o', 'a', and 'i' — three vowels in total.Key Point: Checking both cases in vowelSet avoids a separate call to toLowerCase() for every character.
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 CountVowelsRegex {
public static void main(String[] args) {
String str = "Programming";
// Removes every character that isn't a vowel, leaving only vowels behind
String vowelsOnly = str.replaceAll("[^aeiouAEIOU]", "");
System.out.println("Vowels: " + vowelsOnly.length());
}
}
Output
Core Logic
A regex can strip out every non-vowel in one call, leaving only the vowels behind to count.
- 1
str.replaceAll("[^aeiouAEIOU]", "")matches every character that is NOT a vowel and removes it. - 2What's left is a new string containing only the vowels from the original.
- 3
.length()on that filtered string gives the total vowel count directly.
"Programming" leaves "oai", whose length is 3.Key Point: Regex engines compile the pattern before scanning, which adds overhead a plain loop doesn't have — fine for one-off use, but a hot loop calling this repeatedly would do better with the manual scan.
Why: replaceAll() builds an entirely new filtered string before length() can read its size.
Key Concepts
Approach 3: Java 8
public class CountVowelsStream {
public static void main(String[] args) {
String str = "Programming";
String vowelSet = "aeiouAEIOU";
// filter() keeps only vowel character codes; count() reduces to a single total
long count = str.chars().filter(c -> vowelSet.indexOf(c) != -1).count();
System.out.println("Vowels: " + count);
}
}
Output
Core Logic
The same classification reads as a stream pipeline — filter for vowels, then count what's left.
- 1
str.chars()returns anIntStreamof the string's character codes. - 2
.filter(c -> vowelSet.indexOf(c) != -1)keeps only the codes that appear in the vowel set. - 3
.count()reduces the filtered stream down to a singlelongtotal.
"Programming" keeps only 'o', 'a', and 'i', so count() returns 3.Key Point: count() on a filtered stream reads close to the English description of the problem — 'count the characters that are vowels' — at the cost of a small amount of stream overhead versus the plain loop.
Why: The stream still visits every character once, and count() reduces straight down to a single long without collecting anything.