我需要使用stream()
从HashMap<Integer, Set<Integer>>
获取{10: [100,101], 20:[200,201]}
的新{100: [100], 101: [101], 200:[200], 201:[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
。
答案 0 :(得分:3)
您应该尝试Collectors.groupingBy
:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getValue(),Collectors.toSet()));
我不确定输入Map的类型是什么。如果它是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总是为每个键包含一个值,即一个整数等于该键的Set,你可以忽略该值:
map2 = map1.entrySet()
.stream()
.collect (Collectors.groupingBy (
entry -> entry.getKey()/10,
Collectors.mapping(entry -> entry.getKey(),Collectors.toSet()));
答案 1 :(得分:2)
您可以在没有信息流的情况下执行此操作:
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
不包含空键或任何空值。