有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java8:如何将Map<K,List<D>>上的流转换为Map<D,List<K>>

我刚刚开始研究Java8,为了尝试lambdas,我为上述问题提供了一个用例,我正在使用通常的for循环来解决这个问题,这个循环非常冗长,很难阅读

我现有的代码

private static Map<DataType, List<OperatorType>> buildmap() {

    Map<DataType, List<OperatorType>> map = Maps.newHashMap();

    for (OperatorType type : OperatorType.values()) {
        List<DataType> supportedTypes = type.getSupportedtypes();
        supportedTypes.forEach(datatype -> {
            if (map.containsKey(datatype)) {
                List<OperatorType> list = map.get(datatype);
                list.add(type);
                map.put(datatype,
                        list);
            } else {
                map.put(datatype,
                        new ArrayList<OperatorType>() {
                            private static final long serialVersionUID = 1L;

                            {
                                add(type);
                            }
                        });
            }
        });
    }

    return Collections.unmodifiableMap(new LinkedHashMap<>(map));
}

共 (4) 个答案

  1. # 1 楼答案

    也许像这样的东西有帮助:

    <D, K> Map<D, List<K>> swap(Map<K, List<D>> map) {
      return map.entrySet().stream()
                           .flatMap(e -> e.getValue().stream()
                                                     .map(v -> new SimpleEntry<>(v, e.getKey())))
         .collect(Collectors.groupingBy(Entry::getKey, 
                                        Collectors.mapping(Entry::getValue,
                                                           Collectors.toList())));
    }
    

    流并不总是解决所有问题的最简单方法。请参阅@Flown's answer了解更容易理解的非流解决方案

    你也可以使用.forEach来写Flown的答案“类似流”,但它并没有变得更可读(假设values()getSupportedTypes()都返回一个List),我不建议仅仅说你在使用流:

    OperatorType.values()
      .forEach(type -> type.getSupportedTypes()
        .forEach(dataType -> map.computeIfAbsent(dataType, dt -> new ArrayList<>())
                                                    .add(type)));
    
  2. # 2 楼答案

    一个Stream解决方案需要一些平面映射和元组创建

    你应该坚持嵌套循环

    private static Map<DataType, List<OperatorType>> buildmap() {
      Map<DataType, List<OperatorType>> map = new HashMap<>();
    
      for (OperatorType type : OperatorType.values()) {
        for (DataType dataType : type.getSupportedTypes()) {
          map.computeIfAbsent(dataType, dt -> new ArrayList<>()).add(type);
        }
      }
    
      map.replaceAll((dt, ot) -> Collections.unmodifiableList(ot));
    
      return Collections.unmodifiableMap(map);
    }
    
  3. # 3 楼答案

    下面是一个简单的解决方案StreamEx

    EntryStream.of(map).flatMapValues(v -> v.stream()).invert().grouping();
    
  4. # 4 楼答案

    由于您似乎正在使用Guava,因此可以使用其“展平多贴图”收集器,将其反转并返回地图视图:

    private static Map<DataType, List<OperatorType>> buildmap() {
        ImmutableListMultimap<OperatorType, DataType> flattened =
                Arrays.stream(OperatorType.values())
                        .collect(ImmutableListMultimap.flatteningToImmutableListMultimap(
                                Function.identity(),
                                o -> o.getSupportedtypes().stream()));
        return Multimaps.asMap(flattened.inverse());
    }