如何将地图流转换为单个地图
How to convert Stream of Maps into a single Map
我需要使用流将 Stream<Map<EntityType, Set<String>>>
转换为 Map<EntityType, Set<String>>
。
EntityType
是一个具有特定值的 enum
,比方说 A
、B
和 C
.并且流中有很多地图。
我想使用 Stream API 将它们全部连接成 一个映射 。有什么办法吗?
您可以尝试这样的操作:
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
}
为此,您可以通过应用 flatMap()
展平 流中的 maps。并用 new 包装每个 entry。需要此步骤 1. 以避免源的 突变 和 2. 防止 UnsupportedOperationException
如果 sets 是 unmodifiable.
将被提升
然后申请collect()
.
由于 EntityType
是 enum
,因此 supplier
提供的容器最合适的选择是 EnumMap
,它专为 enum-keys 并且性能优于 HashMap
.
在 combine
方法中 merge()
被应用于 结果映射 以将流中的条目添加到其中。
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));
}
输出
{A=[bar, foobar, foo], B=[bar, abc, fiz, www]}
我需要使用流将 Stream<Map<EntityType, Set<String>>>
转换为 Map<EntityType, Set<String>>
。
EntityType
是一个具有特定值的 enum
,比方说 A
、B
和 C
.并且流中有很多地图。
我想使用 Stream API 将它们全部连接成 一个映射 。有什么办法吗?
您可以尝试这样的操作:
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
}
为此,您可以通过应用 flatMap()
展平 流中的 maps。并用 new 包装每个 entry。需要此步骤 1. 以避免源的 突变 和 2. 防止 UnsupportedOperationException
如果 sets 是 unmodifiable.
然后申请collect()
.
由于 EntityType
是 enum
,因此 supplier
提供的容器最合适的选择是 EnumMap
,它专为 enum-keys 并且性能优于 HashMap
.
在 combine
方法中 merge()
被应用于 结果映射 以将流中的条目添加到其中。
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));
}
输出
{A=[bar, foobar, foo], B=[bar, abc, fiz, www]}