Reputation: 21978
I have an array of arrays of two strings.
var array = new String[][]{
{"a", "1"},
{"a", "2"},
{"b", "3"},
...
};
How can I collect the above array into a Map<String, Set<String>>
whose key is the first element of each array and the value is a set of second elements of the array?
So that I get following map?
// Map<String, Set<String>>
<"a", ["1, "2"]>,
<"b", ["3"]>,
...
So far, I found I can classify the first element of each array like this.
Arrays.stream(array).collect(Collectors.groupingBy(
a -> ((String[])a)[0],
// how can I collect the downstream?
);
Upvotes: 5
Views: 851
Reputation: 6985
Instead of Collectors.groupingBy
, you could use Collectors.toMap
.
public class Main {
public static void main(String[] args) throws Exception {
String[][] array = new String[][]{{"a", "1"}, {"a", "2"}, {"b", "3"}};
Map<String, Set<String>> map = Arrays.stream(array).collect(Collectors.toMap(
arr -> arr[0],
arr -> new HashSet<>(Collections.singleton(arr[1])),
(l, r) -> {
l.addAll(r);
return l;
}));
System.out.println(map);
}
}
First parameter is keyMapper
, second is valueMapper
, third - mergeFunction
.
Upvotes: 1
Reputation: 1711
You can simply do this by using for-each loop
Map<String, Set<String>> map=new HashMap<>();
for(String []arr : array){
Set<String> set = map.getOrDefault(arr[0], new HashSet<>());
set.add(arr[1]);
map.put(arr[0],set);
}
System.out.println(map);
Output :
{a=[1, 2], b=[3]}
Upvotes: 1
Reputation: 28988
Use Collectors.groupingBy
in conjuction with Collectors.mapping()
.
public static void main(String[] args) {
var array = new String[][]{
{"a", "1"},
{"a", "2"},
{"b", "3"}
};
Map<String, Set<String>> result =
Stream.of(array)
.collect(Collectors.groupingBy(arr -> arr[0],
Collectors.mapping(arr -> arr[1],
Collectors.toSet())));
System.out.println(result);
}
Another way of doing this is to utilize Collector.of()
:
Map<String, Set<String>> result =
Stream.of(array)
.collect(Collector.of(
HashMap::new,
(Map<String, Set<String>> map, String[] arr) ->
map.computeIfAbsent(arr[0], k -> new HashSet<>()).add(arr[1]),
(Map<String, Set<String>> left, Map<String, Set<String>> right) ->
{ left.putAll(right); return left; }));
Output
{a=[1, 2], b=[3]}
Upvotes: 4
Reputation: 45319
You can use Collectors.mapping()
with a toSet()
downstream:
Collectors.groupingBy(a -> a[0],
Collectors.mapping(v -> v[1], Collectors.toSet()))
Which produces {a=[1, 2], b=[3]}
. That first maps stream elements to the array's second element, then collects those as a set mapped to the group key.
Upvotes: 4
Reputation: 54148
You need a Collectors.mapping
(also you don't need to specify String[]
inside)
var array = new String[][]{{"a", "1"}, {"a", "2"}, {"b", "3"},};
Map<String, Set<String>> res = Arrays.stream(array).collect(Collectors.groupingBy(
a -> a[0],
Collectors.mapping(a -> a[1], Collectors.toSet())
));
System.out.println(res); // {a=[1, 2], b=[3]}
Upvotes: 2
Reputation: 19
You can loop through your array and for every character you can check if this key is saved before in your map, if yes just push the corresponding character to the list of that repeated key
Upvotes: 0