Reputation: 33
I wish to create a int[] of count for a particular String (comprising of only lowercase English Alphabets) using Java 8 stream API. Where arr[i] denotes the count of i-th character of English dictionary (e.g. arr[0] = count of 'a' in String str while arr[2] = count of 'c' in String str. This can be simply done by:
int[] arr = new int[26];
for(char c : str.toCharArray())
arr[c-'a']++;
Or using IntSream in the 2nd way:
int[] arr = IntStream.range('a','z'+1).map(i -> (int)str.chars().filter(c -> c == i).count()).toArray();
But the problem with the second approach is that the String is traversed 26 times for each of the characters from 'a' to 'z'
Can you suggest a better way of achieving the same using java8-stream API?
PS: I know this can be done using Map but I need int[]
Upvotes: 3
Views: 475
Reputation: 49656
int[] r = str.chars()
.boxed()
.reduce(new int[26],
(a, c) -> { ++a[c - 'a']; return a; },
(a1, a2) -> a1);
You know the former is simpler and better. My answer just proves it's feasible with the Stream API, and doesn't suggest that you should go with it. Personally, I would choose the map approach as the most intuitive one.
As pointed out by @Holger, collect
is a better option here
str.chars()
.map(c -> c - 'a')
.collect(() -> new int[26],
(a, i)-> a[i]++,
(a1, a2) -> /* left as an exercise to the reader*/);
Upvotes: 6
Reputation: 3204
if you want to use streams and keep the iterative approach, you could do it as well like this:
final int count[] = new int[26];
test.chars().forEach(c -> count[c-'a']++);
Upvotes: 2