通过使用 stream() 压缩另一个映射来构建新的 HashMap
Construct new HashMap by compressing the other map with stream()
我需要使用 stream()
从 {100: [100], 101: [101], 200:[200], 201:[201]}
获取新的 HashMap<Integer, Set<Integer>>
,即 {10: [100,101], 20:[200,201]}
我尝试了下面的代码,但当然行不通。
HashMap<Integer, Set<Integer>> map1 = new HashMap<>();
map1.put(100, new HashSet(Arrays.asList(100));
...
HashMap<Integer, Set<Integer>> map2 = map1.entrySet().stream().collect(
Collectors.toMap(entry -> ((Entry<Integer, Set<Integer>>) entry).getKey()/10,
entry -> ((Entry<Integer, Set<Integer>>) entry).getValue()));
这会引发 java.lang.IllegalStateException: Duplicate key
。
你应该试试 Collectors.groupingBy
:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getValue(),Collectors.toSet()));
我不确定输入地图的类型是什么。如果是 HashMap<Integer,Integer>
,我的代码应该可以正常工作。如果它是 HashMap<Integer, Set<Integer>>
,其中 Set<Integer>
只包含一个整数(如您的示例所示),您可以将 entry.getValue()
更改为 entry.getValue().iterator().next()
以获得该整数。
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getValue().iterator().next(),Collectors.toSet()));
想一想,如果您的输入 Map 始终为每个键包含一个值,该值是一个集合,其中单个整数等于该键,您可以忽略该值:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getKey(),Collectors.toSet()));
您可以在没有流的情况下执行此操作:
Map<Integer, Set<Integer>> map2 = new HashMap<>();
map1.forEach((i, s) -> map2.computeIfAbsent(i / 10, ii -> new HashSet<>()).addAll(s));
如果您仍然想使用一个流,即使您的集合有多个值,这仍然有效:
Map<Integer, Set<Integer>> map3 = map1.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getKey() / 10, HashMap::new,
Collector.of(HashSet::new, (s, e) -> s.addAll(e.getValue()),
(a, b) -> {a.addAll(b); return a;},
Collector.Characteristics.UNORDERED)));
这些都假定 map1
不包含空键或任何空值。
我需要使用 stream()
从{100: [100], 101: [101], 200:[200], 201:[201]}
获取新的 HashMap<Integer, Set<Integer>>
,即 {10: [100,101], 20:[200,201]}
我尝试了下面的代码,但当然行不通。
HashMap<Integer, Set<Integer>> map1 = new HashMap<>();
map1.put(100, new HashSet(Arrays.asList(100));
...
HashMap<Integer, Set<Integer>> map2 = map1.entrySet().stream().collect(
Collectors.toMap(entry -> ((Entry<Integer, Set<Integer>>) entry).getKey()/10,
entry -> ((Entry<Integer, Set<Integer>>) entry).getValue()));
这会引发 java.lang.IllegalStateException: Duplicate key
。
你应该试试 Collectors.groupingBy
:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getValue(),Collectors.toSet()));
我不确定输入地图的类型是什么。如果是 HashMap<Integer,Integer>
,我的代码应该可以正常工作。如果它是 HashMap<Integer, Set<Integer>>
,其中 Set<Integer>
只包含一个整数(如您的示例所示),您可以将 entry.getValue()
更改为 entry.getValue().iterator().next()
以获得该整数。
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getValue().iterator().next(),Collectors.toSet()));
想一想,如果您的输入 Map 始终为每个键包含一个值,该值是一个集合,其中单个整数等于该键,您可以忽略该值:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getKey(),Collectors.toSet()));
您可以在没有流的情况下执行此操作:
Map<Integer, Set<Integer>> map2 = new HashMap<>();
map1.forEach((i, s) -> map2.computeIfAbsent(i / 10, ii -> new HashSet<>()).addAll(s));
如果您仍然想使用一个流,即使您的集合有多个值,这仍然有效:
Map<Integer, Set<Integer>> map3 = map1.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getKey() / 10, HashMap::new,
Collector.of(HashSet::new, (s, e) -> s.addAll(e.getValue()),
(a, b) -> {a.addAll(b); return a;},
Collector.Characteristics.UNORDERED)));
这些都假定 map1
不包含空键或任何空值。