Q&A
How to check all the present vowels in a string in Java?
Overview
This is a classic string-traversal exercise that tests your grasp of loops, character handling, case-insensitivity, and set semantics. "Check all present vowels" usually means: report which of the five vowels actually occur in the input (the distinct vowels present), and often also count occurrences.
graph TD
A[Input string] --> B[Convert to lowercase]
B --> C{For each character}
C --> D{Is it a vowel?}
D -->|yes| E[Add to result set]
D -->|no| C
E --> C
C -->|done| F[Set of present vowels]
style F fill:#1e1b4b,color:#fff
Approach 1: Using a Set (distinct vowels present)
A Set automatically de-duplicates, so it answers "which vowels are present" directly.
import java.util.*;
public class Vowels {
public static Set<Character> presentVowels(String input) {
Set<Character> vowels = Set.of('a', 'e', 'i', 'o', 'u');
Set<Character> found = new LinkedHashSet<>(); // preserves insertion order
for (char c : input.toLowerCase().toCharArray()) {
if (vowels.contains(c)) {
found.add(c);
}
}
return found;
}
public static void main(String[] args) {
System.out.println(presentVowels("Educative")); // [e, u, a, i]
System.out.println(presentVowels("rhythm")); // []
}
}
toLowerCase() handles case-insensitivity so 'A' and 'a' are treated alike. LinkedHashSet keeps the order in which vowels were first seen; use TreeSet if you want them sorted alphabetically.
Approach 2: Counting each vowel's occurrences
If you also need how many times each vowel appears, use a Map:
import java.util.*;
public static Map<Character, Integer> vowelCounts(String input) {
Set<Character> vowels = Set.of('a', 'e', 'i', 'o', 'u');
Map<Character, Integer> counts = new TreeMap<>(); // sorted output
for (char c : input.toLowerCase().toCharArray()) {
if (vowels.contains(c)) {
counts.merge(c, 1, Integer::sum);
}
}
return counts;
}
// vowelCounts("Education") -> {a=1, e=1, i=1, o=1, u=1}
merge(c, 1, Integer::sum) is a concise idiom: insert 1 if absent, otherwise add 1 to the existing count.
Approach 3: Java Streams (functional style)
import java.util.stream.*;
public static Set<Character> presentVowelsStream(String input) {
return input.toLowerCase().chars() // IntStream of code points
.mapToObj(c -> (char) c)
.filter(c -> "aeiou".indexOf(c) >= 0)
.collect(Collectors.toCollection(LinkedHashSet::new));
}
This is compact and expressive, though slightly less readable for beginners than the explicit loop.
Edge Cases to Mention
- Uppercase/lowercase - normalize with
toLowerCase(). nullor empty input - guard againstNullPointerException; an empty string yields an empty result.- Whether
ycounts - sometimes treated as a vowel; clarify with the interviewer. - Non-Latin / Unicode -
chars()works on UTF-16 code units; for full Unicode usecodePoints().
public static Set<Character> presentVowels(String input) {
if (input == null || input.isEmpty()) return Set.of();
// ... as above
}
Complexity
All approaches are O(n) time (single pass over the string) and O(1) extra space (the result set holds at most 5 vowels).
Why This Matters in Interviews
This question checks fundamentals: choosing the right data structure (set for presence, map for counts), handling case and edge cases, and knowing both imperative and functional styles. Mentioning complexity and edge cases unprompted is a strong signal.
Common Pitfalls
- Forgetting case normalization, so
'A'is missed. - Using a
Listand getting duplicates when you wanted distinct vowels. - Not handling
null/empty input. - Comparing with
==on boxedCharacter(use primitives or.equals()).
References
- Java
Set/Mapdocs: https://docs.oracle.com/en/java/javase/17/docs/api/ - Java Streams tutorial: https://docs.oracle.com/javase/tutorial/collections/streams/