You can use groupingBy instead of toMap:
Map<String, Set<A>> sysUidToAMap =
mySet.stream()
.collect(Collectors.groupingBy(A::getSystemID,
Collectors.toSet()));
Answer from Eran on Stack OverflowYou can use groupingBy instead of toMap:
Map<String, Set<A>> sysUidToAMap =
mySet.stream()
.collect(Collectors.groupingBy(A::getSystemID,
Collectors.toSet()));
my 2¢: you can do it with Collectors.toMap but it's slightly more verbose:
yourSet
.stream()
.collect(Collectors.toMap(
A::getSystemId,
a -> {
Set<A> set = new HashSet<>();
set.add(a);
return set;
}, (left, right) -> {
left.addAll(right);
return left;
}));
I ended up with a fairly straight-forward one line solution with Java 8 as follows:
Map<String, Foo> map = fooSet.stream().collect(Collectors.toMap(Foo::getKey, e -> e));
- fooSet is a set of objects of type Foo, i.e.
Set<Foo> fooSet - Foo has a getter called
getKeywhich returns a String
Improvement of developer's answer:
Map<String, Foo> map = fooSet.stream().collect(Collectors.toMap(Foo::getKey, Function.identity()));
or if you statically import Collectors.toMap and Function.identity:
Map<String, Foo> map = fooSet.stream().collect(toMap(Foo::getKey, identity()));
Use
// in Java 22+, you should name the "k" below as "_"
map.computeIfAbsent(node1, k -> new LinkedHashSet<>()).add(node2);
If node1 is already found in the map, it will be equivalent to:
map.get(node1).add(node2);
If node1 is not already in the map, it will be equivalent to:
map.put(node1, new LinkedHashSet<>()).add(node2);
This is exactly what you're looking for, and is even described as a use case in the documentation.
you can also use
map.merge(node1,new LinkedHashSet<>(),(v1,v2)->v1!=null?v1:v2).add(node2);
and also
map.compute(node1,(k,v)->v!=null?v:new LinkedHashSet<>()).add(node2);
You can use a series of Stream.map and Stream.flatMap:
List<Map<String, List<String>>> input = ...;
Set<String> output = input.stream() // -> Stream<Map<String, List<String>>>
.map(Map::values) // -> Stream<List<List<String>>>
.flatMap(Collection::stream) // -> Stream<List<String>>
.flatMap(Collection::stream) // -> Stream<String>
.collect(Collectors.toSet()) // -> Set<String>
;
Use flatMap for this purpose
List< Map<String, List<String>> > maps = ...
Set<String> result = maps.stream()
.flatMap(m -> m.values().stream())
.flatMap(List::stream)
.collect(Collectors.toSet());
Try something like this:
import static java.util.stream.Collectors.*;
import org.apache.commons.lang3.tuple.Pair;
// ...snip...
sections.stream()
.flatMap(section->section.getGrids()
.stream()
.map(Grid::getRows)
.flatMap(Set::stream)
.map(row->new Pair(row.getEmail(), section.getId())))
.collect(groupingBy(Pair::getKey, mapping(Pair::getValue, toSet())));
If you're using Java 9 or newer, your can do it in a very concise way without the need of third party libraries:
import java.util.Map;
import java.util.Set;
import static java.util.Map.Entry;
import static java.util.Map.entry;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toSet;
Map<String, Set<Long>> result = sections.stream()
.flatMap(section -> section.getGrids().stream()
.flatMap(grid -> grid.getRows().stream())
.map(row -> entry(row.getEmail(), section.getId())))
.collect(groupingBy(Entry::getKey, mapping(Entry::getValue, toSet())));