将Map <?、 Map <?,?>转换为对象列表

时间:2020-04-29 19:48:46

标签: java java-8 java-stream

我有以下收藏:

Map<String, Map<SomeEnum, Long>> map = ...

以下是示例数据:

{"Foo": {
    SomeEnum.BAR1: 1,
    SomeEnum.BAR2: 2,
    SomeEnum.BAR3: 3
  },
 "two": {...}

由于我知道所有枚举,因此我想将其转换为POJO列表。对象的定义如下:

class SomeClass {
  String name;
  long bar1Value;
  long bar2Value;
  long bar3Value;
}

我尝试了不同的解决方案,例如在映射内部进行映射:

map.entrySet().stream()
.map(e -> e.getValue().entrySet().stream().map(innerEntry -> {
  long bar1 = 0;
  long bar2 = 0;
  long bar3 = 0;

  if(innerEntry.getKey().equals(SomeEnum.BAR1)) bar1 = innerEntry.getValue();
  if(innerEntry.getKey().equals(SomeEnum.BAR2)) bar2 = innerEntry.getValue();
  if(innerEntry.getKey().equals(SomeEnum.BAR3)) bar3 = innerEntry.getValue();

  return new SomeClass(e.getKey(), bar1, bar2, bar3);
}).collect(toList()).collect(toList());

不幸的是,我得到的是List<List<SomeClass>>

还有其他更优雅的方式来处理此问题吗?

5 个答案:

答案 0 :(得分:5)

这对您有用吗?

它需要目标类的构造函数,但仅获取值并创建实例。然后将它们收集到列表中。

        List<SomeClass> list = map.entrySet().stream()
                .map(e -> new SomeClass(e.getKey(),
                        e.getValue().get(SomeEnum.BAR1),
                        e.getValue().get(SomeEnum.BAR2),
                        e.getValue().get(SomeEnum.BAR3)))
                .collect(Collectors.toList());

带有构造函数的类


class SomeClass {
    String name;
    long bar1Value;
    long bar2Value;
    long bar3Value;

    public SomeClass(String name, long bar1Value, long bar2Value,
        long bar3Value) {
        this.name = name;
        this.bar1Value = bar1Value;
        this.bar2Value = bar2Value;
        this.bar3Value = bar3Value;
    }       
}

答案 1 :(得分:4)

您可以使用实用程序从内部映射中创建df$species <- sub(".*\\*{3}retired\\*{3}use\\s+", "", df$species) 来简化整个任务:

SomeClass

然后您的映射就像-

private SomeClass createSomeClass(String name, Map<SomeEnum, Long> innerMap) {
    return SomeClass.builder()
            .name(name)
            .bar1Value(innerMap.getOrDefault(SomeEnum.BAR1, 0L))
            .bar2Value(innerMap.getOrDefault(SomeEnum.BAR2, 0L))
            .bar3Value(innerMap.getOrDefault(SomeEnum.BAR3, 0L))
            .build();
}

答案 2 :(得分:2)

map更改为flatMap并删除第一个toList()

List<SomeClass> ss = map.entrySet().stream()
                .flatMap(e -> e.getValue().entrySet().stream().map(innerEntry -> {
                    long bar1 = 0;
                    long bar2 = 0;
                    long bar3 = 0;

                    if(innerEntry.getKey().equals(SomeEnum.BAR1)) bar1 = innerEntry.getValue();
                    if(innerEntry.getKey().equals(SomeEnum.BAR2)) bar2 = innerEntry.getValue();
                    if(innerEntry.getKey().equals(SomeEnum.BAR3)) bar3 = innerEntry.getValue();

                    return new SomeClass(e.getKey(), bar1, bar2, bar3);
                })).collect(Collectors.toList());

答案 3 :(得分:1)

您必须这样做:

首先添加一种方法来为每个枚举值设置特定的长整数,如下所示:

class SomeClass {

    String name;
    long bar1Value;
    long bar2Value;
    long bar3Value;

//获取器和设置器

    public void setByEnum(SomeEnum t, Long value) {
        switch (t) {
            case BAR1:
                this.setBar1Value(value);
                break;
            case BAR2:
                this.setBar2Value(value);
                break;
            case BAR3:
                this.setBar3Value(value);
                break;
        }
    }
}

然后,您需要使地图循环播放,如下所示:

 List<SomeClass> list = new ArrayList<>();
    map.forEach((name,values)->{
        SomeClass s = new SomeClass();
        s.setName(name);
        values.forEach((t,value)->{
            s.setByEnum(t, value);
        });
        list.add(s);
    });

答案 4 :(得分:0)

那这样的事情呢?

ArrayList<Integer> keyList = new ArrayList<Integer>(map.keySet());
for(int i=0; i<keyList.size(); i++){
    Map innermap = map.get(keyList.get(i));
    SomeClass obj = new SomeClass(keyList.get(i),innermap.get('bar1'),innermap.get('bar2'),innermap.get('bar3');
}