英文:
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<AreaDate, Map<AreaCategory, List<Location>> dateWiseAreas
using java 8 I want to build a map of
 Map<Area, Map<AreaCategory, List<Location>> areas
I used the below logic and I get a duplicate key error saying Area key is duplicate
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))));
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<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
));
答案2
得分: 0
你可以使用toMap()的重载版本,该版本允许您传递一个BinaryOperator<V>,其中在您的情况下,V是Map<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<V> where V in your case is Map<AreaCategory, List<Location>>
Map<Area, Map<AreaCategory, List<Location>> areas = dateWiseAreas.entrySet().stream()
    .collect(Collectors.toMap(
        e -> e.getKey().area(),
        Map.Entry::getValue, // there seems to be no need to copy the whole thing again
        (a, b) -> {
            // merging Map b into Map a
            b.forEach((key, values) -> a.merge(key, values, (c, d) -> {
                // adding all locations from d to a
                c.addAll(d);
                return c;
            });
            return b;
        })
    );
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论