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



我有以下集合:

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>>

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

这对你有用吗?

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

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;
}       
}

您可以使用一个从内部映射创建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();
}

然后你的地图就会像一样简单

List<SomeClass> someClassList = map.entrySet().stream()
.map(e -> createSomeClass(e.getKey(), e.getValue()))
.collect(Collectors.toList());

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());

你必须这样做:

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

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);
});

这样的东西怎么样:

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');
}

最新更新