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?
CodePudding user response:
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]}
CodePudding user response:
Another approach using Collections.frequency
and a Map<Long, Set<String>>
to avoid having duplicates in the values:
final String input = "Hello world Hello Stackoverflow";
List<String> list = Arrays.stream(input.split(" ")).collect(Collectors.toList());
final Map<Long, Set<String>> output = list.stream()
.collect(Collectors.groupingBy(
str -> (long) Collections.frequency(list, str), Collectors.toSet()));
CodePudding user response:
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.
- create a destination map.
- iterate over the entrySet
computeIfAbsent
will create the list if the key is not present.- it also returns the just created or existing value, a list in this case, so you can add the word.
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]