从地图Java 8

时间:2016-10-24 22:11:06

标签: java java-8 java-stream

我有一个Map<String, List<SomeClassA>>,我试图转换为Map<String, Map<String, List<SomeWrapperOfClassA>>>,而我在如何解决这个问题时遇到了很多麻烦。

实际上,创建地图所​​需的所有信息都应该在SomeClassA类型的对象中 - 比如说

SomeClassA:
   String attributeA;
   String attributeB;
   SomeClassB someOtherInfo;

SomeClassB:
   String attribute C;

我想说它是基于此的地图:

Map<attributeA's values,Map<attribute C vals, List SomeWrapperOfClassA>> 其中列表只包含具有attributeA和attributeB值的SomeWrapperClassA。我当时认为它可能与groupingBy有关,但我不太熟悉如何以这样的方式嵌套它。

(或者为了简单起见,将SomeClassA的原始列表添加到Map<String, Map<String, List<SomeClassA>>>中的任何帮助都已经是一个巨大的帮助。

我还没有完全掌握Java 8和更复杂的流媒体概念,所以一些帮助将不胜感激。我只熟悉基础知识。

3 个答案:

答案 0 :(得分:0)

我不确定你的意思是:  Map<String, Map<String, List<SomeClassA>>>,分组的关键是什么?一般来说,如果你想通过someClassA中的attributeA对List<SomeClassA>进行分组,你可以这样做:

 List<SomeClassA>.stream().collect(Collectors.groupingBy(someClsA-> someClsA.getAttributeA()));

答案 1 :(得分:0)

如果我理解你的问题,我会表达如下:

假设:

class ClassA {
    public String getA();
    public ClassB getB();
}

class ClassB {
    public String getC();
}

Map<String, List<ClassA>> input;

我如何创建Map<String, Map<String, List<ClassB>>,其中内部地图的键是getA的结果?

如果这是正确的,那么你根本不想改变外部地图的键。这使它成为Map.replaceAll的合适人选。为了清楚起见,我将收集器拆分为一个单独的方法,以便清楚发生了什么:

input.replaceAll(listA.stream().collect(mapCollector()));

private Collector<A, ?, Map<String, List<B>> mapCollector() {
    return Collectors.groupingBy(ClassA::getA,
        Collectors.mapping(ClassA::getB,
            Collectors.toList()));
}

通过A作为关键字解释组getA的方法,然后使用A通过映射收集这些getB,然后放入列表。

如果您特别想要新地图(而不是更改原始地图),那么:

Map<String, Map<String, List<ClassB>>> output = input.entrySet().stream()
    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream().collect(mapCollector()));

答案 2 :(得分:0)

您想要实现的目标并不完全清楚。显然,源映射的键是无关紧要的,您只想处理值列表中包含的SomeClassA实例。因此,第一步是流式传输地图的值,即sourceMap.values().stream(),然后通过Stream<List<SomeClassA>>将此Stream<SomeClassA>展平为flatMap(List::stream)

通过其中一个属性对这些SomeClassA实例进行分组,确实可以通过groupingBy直接进行,这需要另一个嵌套groupingBy来进一步按“属性C”对每个组进行分组:

Map<String, Map<String, List<SomeClassA>>> resultMap
    = sourceMap.values().stream().flatMap(List::stream)
        .collect(Collectors.groupingBy(SomeClassA::getAttributeA,
                     Collectors.groupingBy(a->a.getSomeOtherInfo().getAttributeC())));

要将SomeClassA个实例转换为SomeWrapperClassA个实例,我们需要另一个最内层groupingBy的嵌套收集器; mapping收集器允许在传输到另一个收集器之前映射值,该收集器必须是toList()收集器,以前是隐含的。

现在,开始使用import static java.util.stream.Collectors.*;

可能会更好
Map<String, Map<String, List<SomeWrapperClassA>>> resultMap
  = sourceMap.values().stream().flatMap(List::stream)
    .collect(groupingBy(SomeClassA::getAttributeA, groupingBy(
      a -> a.getSomeOtherInfo().getAttributeC(),
      mapping(a->new SomeWrapperClassA(a.getAttributeA(),a.getAttributeB()), toList()))));