Reputation: 103
I'm trying to understand a data flow of streams in Java. My task is to put occurrences of each letter in list of strings
List<String> words = Arrays.asList("Welcome", "to", "the", "java", "world");
into
Map<String, Long>
using a one-liner stream.
I know, that in the first place we can stream each word from the list, then I need to separate it into chars, then put each char as key and count its occurrence as value and in the end return the whole map.
It is so complicated to understand. Could someone explain to me how to do it?
Upvotes: 3
Views: 26868
Reputation: 1
This looks simpler to me.
Map<String, Long> charCount = words.stream().map(s -> s.split("")).flatMap(Arrays::stream)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
{a=2, c=1, d=1, e=3, h=1, j=1, l=2, m=1, o=3, r=1, t=2, v=1, w=1, W=1}
Upvotes: 0
Reputation: 271
In Kotlin:
val str = "Occurrences"
val results: Map<String, Long> =
stream(str.split("").toTypedArray()).map{n-> n.lowercase()}
.collect(
Collectors.groupingBy({ it },
{ LinkedHashMap() },
Collectors.counting()
)
)
Log.w("occurrencesResult",results.toString())
Upvotes: 0
Reputation: 21
More readable using flatMapToInt
than flatMap(a -> a.chars().mapToObj(c -> (char) c))
words.stream()
.flatMapToInt(String::chars) //IntStream
.mapToObj(c -> (char) c) //Stream<Character>
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Upvotes: 2
Reputation: 31878
It could be done as Willis pointed out using the flatMap
and groupingBy
collector. But, the expected output type should be Map<Character, Long>
fo that as in:
Map<Character, Long> charFrequency = words.stream() //Stream<String>
.flatMap(a -> a.chars().mapToObj(c -> (char) c)) // Stream<Character>
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Upvotes: 10
Reputation: 8204
The thing you need to know is that flatMap
is the function that you can use to convert the strings into individual characters. While regular map
function just converts each stream element into a different element, flatMap
converts each element into a stream of elements, then concatenates those streams together.
The function that converts a String
into a stream of characters is String.chars
.
When you want to build a new collection from a stream, you usually use a collector. Using the function Collectors.groupingBy
you can produce a collector that will create a Map
, given two functions, one to produce the key for each stream value, and the other to produce the value. There's a variant of this that will let you pass another collector in as the second parameter instead of a function; try Collectors.counting
.
Upvotes: 2