使用Java 8的流(streams)来从另一个嵌套的Map构建一个Map of Map。

huangapple go评论96阅读模式
英文:

Using java 8 streams to build a map of map from another map of map

问题

我在Java中有一个Map集合

    Map<AreaDate, Map<AreaCategory, List<Location>>> dateWiseAreas

使用Java 8我想构建一个地区映射

    Map<Area, Map<AreaCategory, List<Location>>> areas

**我使用了以下逻辑但是出现了重复的键错误提示Area键是重复的**

    Map<Area, Map<AreaCategory, List<Location>>> areas = dateWiseAreas.entrySet().stream()
    .collect(Collectors.toMap(
                   k -> k.getKey().area(),
                   v -> v.getValue()
                         .entrySet()
                         .stream()
                         .collect(Collectors.toMap(
                                 Map.Entry::getKey, Map.Entry::getValue,
                                 (oldValue, newValue) -> oldValue, LinkedHashMap::new))));

Java类

    enum Area {
       EUROPE,
       AUSTRALIA,
       ASIA;   
    }

    class AreaDate {
     Area area;
     LocalDate date;
     int priority;
    }

    enum AreaCategory {
      NORTH,
      SOUTH,
      WEST,
      EAST;
    }

    class Location {
     int xaxis;
     int yaxis;
    }
英文:

I have a Map collection in java

Map&lt;AreaDate, Map&lt;AreaCategory, List&lt;Location&gt;&gt; dateWiseAreas

using java 8 I want to build a map of

 Map&lt;Area, Map&lt;AreaCategory, List&lt;Location&gt;&gt; areas

I used the below logic and I get a duplicate key error saying Area key is duplicate

Map&lt;Area, Map&lt;AreaCategory, List&lt;Location&gt;&gt; areas =  dateWiseAreas.entrySet().stream()
.collect(toMap(k -&gt; k.getKey().area(),
               v -&gt; v.getValue()
                     .entrySet()
                     .stream()
                     .collect(Collectors.toMap(Map.Entry::getKey(), Map::Entry::getValue,
                             (oldValue,newValue) -&gt; oldValue, LinkedHashMap::new))));

Java classes

Area {
   EUROPE,
   AUSTRALIA,
   ASIA;   
}


AreaDate {
 Area area;
 LocalDate date;
 int priority;
}

AreaCategory {
  NORTH,
  SOUTH,
  WEST,
  EAST;
}

Location {
 int xaxis;
 int yaxis;
}

答案1

得分: 0

你需要在外部的collect中使用toMap的三个参数版本,以避免在同一个区域在不同日期下出现多次且日期不同的情况下出现冲突的键。

类似这样(未经测试):

Map<Area, Map<AreaCategory, List<Location>>> areas = dateWiseAreas.entrySet().stream()
.collect(toMap(k -> k.getKey().area(),
               v -> v.getValue()
                     .entrySet()
                     .stream()
                     .collect(Collectors.toMap(Map.Entry::getKey(), Map.Entry::getValue,
                             (oldValue, newValue) -> oldValue, LinkedHashMap::new)),
              (oldValue, newValue) -> oldValue
));
英文:

You need to use the 3 argument version of toMap in the outer collect to avoid conflict on keys where the same area is found multiple times with different dates.

Something like (untested)

Map&lt;Area, Map&lt;AreaCategory, List&lt;Location&gt;&gt; areas =  dateWiseAreas.entrySet().stream()
.collect(toMap(k -&gt; k.getKey().area(),
               v -&gt; v.getValue()
                     .entrySet()
                     .stream()
                     .collect(Collectors.toMap(Map.Entry::getKey(), Map::Entry::getValue,
                             (oldValue,newValue) -&gt; oldValue, LinkedHashMap::new)),
              (oldValue, newvalue) -&gt; oldValue
));

答案2

得分: 0

你可以使用toMap()的重载版本,该版本允许您传递一个BinaryOperator<V>,其中在您的情况下,VMap<AreaCategory, List<Location>>

Map<Area, Map<AreaCategory, List<Location>>> areas = dateWiseAreas.entrySet().stream()
    .collect(Collectors.toMap(
        e -> e.getKey().area(),
        Map.Entry::getValue, // 似乎没有必要再复制整个内容
        (a, b) -> {
            // 将Map b合并到Map a
            b.forEach((key, values) -> a.merge(key, values, (c, d) -> {
                // 将d中的所有位置添加到a
                c.addAll(d);
                return c;
            });
            return b;
        })
    );
英文:

You can use the overload of toMap() which allows you to pass a BinaryOperator&lt;V&gt; where V in your case is Map&lt;AreaCategory, List&lt;Location&gt;&gt;

Map&lt;Area, Map&lt;AreaCategory, List&lt;Location&gt;&gt; areas = dateWiseAreas.entrySet().stream()
    .collect(Collectors.toMap(
        e -&gt; e.getKey().area(),
        Map.Entry::getValue, // there seems to be no need to copy the whole thing again
        (a, b) -&gt; {
            // merging Map b into Map a
            b.forEach((key, values) -&gt; a.merge(key, values, (c, d) -&gt; {
                // adding all locations from d to a
                c.addAll(d);
                return c;
            });
            return b;
        })
    );

huangapple
  • 本文由 发表于 2020年10月1日 23:02:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/64158091.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定