问题
Given mapping of letters to numbers, I would like to return a list of Strings, where each String is a comma delimited list of the letters grouped by their associated number.
For this map
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 4);
map.put("D", 1);
map.put("E", 1);
map.put("F", 2);
I would like to return a List containing:
"A,D,E" "B,F", "C"
Any suggestions how this can be accomplished using the 1.8 streaming functions?
回答1:
This way doesn't reference map
after it's initially streamed, and makes maximal use of the streaming facilities:
return map.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
.values().stream().collect(Collectors.toList());
Or more concisely, but with less usage of streams (thanks @Kartik):
return new ArrayList<>(map.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
.values());
In either of those, if you add TreeMap::new
as an argument between the two existing arguments to Collectors.groupingBy
, the "inside" pieces will be sorted.
回答2:
You can first group entries by value, and then use Collectors.joining(",")
:
List<String> result = map.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue))
.values().stream()
.map(e -> e.stream()
.map(Map.Entry::getKey)
.collect(Collectors.joining(",")))
.collect(Collectors.toList());
回答3:
Here's my attempt
List<String> results = map
.entrySet()
.stream()
.collect(
Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(
Map.Entry::getKey,
Collectors.toList())))
.values()
.stream()
.map(letters -> String.join(",", letters))
.collect(Collectors.toList());
来源:https://stackoverflow.com/questions/55055555/how-to-flatten-and-group-this-hashmap-using-streams