I need to count the number of vowels in a list of words in Functional Java. If I have this list:
List<String> l = Arrays.asList("hello", "world", "test");
My idea was to "delete" the vowels and then do a subtraction this way:
int tot = l.stream().map(s -> s.replace("a", "")).
map(s -> s.replace("e", "")).
map(s -> s.replace("i", "")).
map(s -> s.replace("o", "")).
map(s -> s.replace("u", "")).
map(s -> s.length()).reduce(0, Integer::sum);
int res = l.stream().map(s->s.length()).reduce(0, Integer::sum)-tot;
Is there a better way to do this?
To find the vowels in a given string, you need to compare every character in the given string with the vowel letters, which can be done through the charAt() and length() methods. charAt() : The charAt() function in Java is used to read characters at a particular index number.
replaceAll("[^aeiouAEIOU]",""). length(); and subtract from the Original word. you will get the count of vowels.
How about this:
List<String> vowels = Arrays.asList("a", "e", "i", "o", "u");
int count Arrays.stream(string.split("")) // generate stream from an String[] of single character strings
.filter(vowels::contains) // remove all non-vowels
.count(); // count the elements remaining
You can eliminate multiple map
with one map
using replaceAll
int tot = l.stream()
.map(s -> s.replaceAll("[aeiou]", "").length())
.reduce(0, Integer::sum);
[aeiou]
it will match any char inside []
and replace it with empty string
I'd break it to stream of chars, filter only vowels and then count:
int tot = l.stream()
.flatmap(s -> s.chars().stream())
.filter(c -> c == 'a' || c == 'e' ||c == 'i' ||c == 'o' ||c == 'u')
.count();
You're probably concerned about the multiple replace
calls, which isn't really related to functional programming. One way to replace those calls is to use a regular expression and replaceAll
:
.map(s -> s.replaceAll("[aeiou]", ""))
This single map replaces all 5 maps that removes the vowels.
With a regular expression, you could also remove all the non-vowels. This way, you don't have to subtract tot
:
int vowels = l.stream().map(s -> s.replaceAll("[^aeiou]", ""))
.map(s -> s.length()).reduce(0, Integer::sum);
// no need to do anything else!
Now you still have two consecutive map
s, you can combine them into one:
int vowels = l.stream().map(s -> s.replaceAll("[^aeiou]", "").length())
.reduce(0, Integer::sum);
This is now more functional because I've removed the step of subtracting tot
. This operation is now described only as a composition of function (as far as this level of abstraction is concerned), instead of a bunch of "steps".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With