Reputation: 604
I'm having below sentence
Hello world Hello Stackoverflow
Expected output: (order is not concern)
{2=[Hello], 1=[world,Stackoverflow]}
Tried with below code:
final String input = "Hello world Hello Stackoverflow";
final Map<String, Long> output = Arrays.stream(input.split(" "))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(output);
got below output:
{world=1, Hello=2, Stackoverflow=1}
I want to get Long
as key and List<String>
as value in Map
How to do this?
Upvotes: 0
Views: 220
Reputation: 40034
is it possible to do in single stream?
Not really (or probably not as efficiently). You need to have the frequency of each word to use as a key. Continually updating the key during map construction is fraught with problems. And you would need to update the lists as well.
However, the following does the exact same thing but without a stream. So it is probably a little more efficient. And you can use your just created map as the source.
computeIfAbsent
will create the list if the key is not present.Map<Long, List<String>> result = new HashMap<>();
for (Entry<String,Long> e : output.entrySet()) {
result.computeIfAbsent(e.getValue(), v->new ArrayList<>())
.add(e.getKey());
}
result.entrySet().forEach(System.out::println);
prints
1=[world, Stackoverflow]
2=[Hello]
Upvotes: 2
Reputation: 18113
You need to group the Map entries like this :
String input = "Hello world Hello Stackoverflow";
Map<Long, List<String>> output = Arrays.stream(input.split(" "))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet() // Set<Entry<String, Long>>
.stream() // Stream<Entry<String, Long>>
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())
));
System.out.println(output); // {1=[world, Stackoverflow], 2=[Hello]}
Upvotes: 4