通过使用stream()压缩其他映射来构造新的HashMap

时间:2015-01-30 02:50:27

标签: java java-8

我需要使用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

2 个答案:

答案 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不包含空键或任何空值。