I need to use streams to convert the Stream<Map<EntityType, Set<String>>>
to Map<EntityType, Set<String>>
.
The EntityType
is an enum
having certain values, let's say A
, B
and C
. And there are lots of maps in the stream.
I want to concatenate all of them into one map using Stream API . Is there any way?
You could try something like this:
public static void main(String[] args) {
Map<EntityType, Set<String>> mapA = Map.of(EntityType.A, Set.of("1", "2", "3"), EntityType.B, Set.of("4", "5", "6"));
Map<EntityType, Set<String>> mapB = Map.of(EntityType.A, Set.of("1", "4", "5"), EntityType.C, Set.of("4", "5", "6"));
Map<EntityType, Set<String>> mapC = Map.of(EntityType.A, Set.of("3", "7", "5"), EntityType.B, Set.of("4", "9", "6"));
// The stream calls you can try:
Map<EntityType, Set<String>> result = Stream.of(mapA, mapB, mapC)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(keyValuePair -> keyValuePair.getKey(),
keyValuePair -> keyValuePair.getValue(),
(value1, value2) -> combine(value1, value2)));
}
private static <T> Set<T> combine(Set<T>... sets) {
return Stream.of(sets)
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
enum EntityType {
A,
B,
C
}
For that, you can flatten the maps in the stream by applying flatMap()
. And wrap each entry with a new one. This step is required 1. to avoid mutation of the source and 2. to prevent an UnsupportedOperationException
which will be raised if sets are unmodifiable .
And then apply collect()
.
Since EntityType
is an enum
the most appropriate choice for the container provided by the supplier
will be an EnumMap
which was designed specifically for enum-keys and has a better performance than HashMap
.
Inside the combine
method merge()
is being applied on the resulting map to add entries from the stream into it.
public static <T extends Enum<T>, U> Map<T, Set<U>> collect(Stream<Map<T, Set<U>>> source,
Class<T> enumClass) {
return source
.flatMap(map -> map.entrySet().stream()
.map(entry -> Map.entry(entry.getKey(), new HashSet<>(entry.getValue()))))
.collect(() -> new EnumMap<>(enumClass),
(map, entry) -> map.merge(entry.getKey(),
entry.getValue(),
(v1, v2) -> {v1.addAll(v2); return v1;}),
Map::putAll);
}
main()
public static void main(String[] args) {
Stream<Map<EntityType, Set<String>>> source =
Stream.of(Map.of(EntityType.A, Set.of("foo"), EntityType.B, Set.of("bar")),
Map.of(EntityType.A, Set.of("foo", "bar"), EntityType.B, Set.of("bar", "fiz")),
Map.of(EntityType.A, Set.of("foobar"), EntityType.B, Set.of("abc", "www")));
System.out.println(collect(source, EntityType.class));
}
Output
{A=[bar, foobar, foo], B=[bar, abc, fiz, www]}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.