如何使用lambdas/stream将嵌套的对象列表转换为映射(Map<Integer,Map<Integer,Object>>)



我正在使用两个for循环将以下对象结构列表转换为HashMap,如下所示。

public class Vehical {
private Category category;
private List<Brand> brandList;
public Category getCategory() {
return category;
}
public List<Brand> getBrandList() {
return brandList;
}
}

public class Category {
private Integer catId;
public Integer getCatId() {
return catId;
}       
}

public class Brand {
private Model model;
public Model getModel() {
return model;
}
}

public class Model {
private List<Reg> regList;
public List<Reg> getRegList() {
return regList;
}
}

public class Reg {
private Integer regId;
public Integer getRegId() {
return regId;
}
}

public static void main(String[] args) {
//Assume that filled with data.*** 
List<Vehical> vehicalList = getVehicals();
Map<Integer, Map<Integer, Brand>> vehicalMap = new HashMap<Integer, Map<Integer, Brand>>();
for (Vehical vehical : vehicalList) {
Map<Integer, Brand> brandMap = new HashMap<Integer, Brand>();
for (Brand brand : vehical.getBrandList()) {
//Assume that zeroth index is always available and getting "RegId" from the zeroth element is fixed.***
brandMap.put(brand.getModel().getRegList().get(0).getRegId(), brand);
}
vehicalMap.put(vehical.getCategory().getCatId(), brandMap);
}
}

如何使用 lambdas/流做同样的事情? 我尝试使用flatMap,但它不起作用。流式传输时无法访问嵌套的 RegId。

另外,我尝试了forEach,但最终它看起来像相同的循环解决方案。

Map<Integer, Map<Integer, Brand>> vehicalMap = new HashMap<>();
vehicalList.forEach(v -> {
Map<Integer, Brand> brandMap = new HashMap<>();
v.getBrandList().stream().forEach(b -> brandMap
.put(b.getModel().getRegList().get(0).getRegId(), b));
vehicalMap.put(v.getCategory().getCatId(), brandMap);
});

任何帮助将不胜感激。

更新基于@Nidhish克里希南答案的工作代码示例

试试这个

解决方案 1

如果您想获得基于分组的结果,请尝试这个

Map<Integer, Map<Integer, Brand>> vehicalMap = getVehicals().stream()
.collect(Collectors.groupingBy(vechiles -> vechiles.getCategory().getCatId(),
Collectors.collectingAndThen(
Collectors.groupingBy(vechile -> vechile.getBrandList().get(0).getModel().getRegList().get(0).getRegId()),
e ->e.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().get(0).getBrandList().get(0)))
)
))
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

解决方案 2

如果您不想使用分组,请尝试以下方法

Map<Integer, Map<Integer, Brand>> vehicalMap = getVehicals().stream()
.collect(Collectors.toMap(
vechile -> vechile.getCategory().getCatId(),
vechile -> vechile.getBrandList().stream()
.collect(Collectors.toMap(
brands -> brands.getModel().getRegList().get(0).getRegId(), 
brand -> brand, (a, b) -> b)), 
(a, b) -> a));

更新 1

不确定您vehicalList有什么数据,这就是我创建测试vehicalList

private static List<Vehical> getVehicals() {
return Lists.newArrayList(
new Vehical(new Category(21), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(100), new Reg(101), new Reg(102)))))),
new Vehical(new Category(22), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(200), new Reg(201), new Reg(202)))))),
new Vehical(new Category(23), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(300), new Reg(301), new Reg(302)))))),
new Vehical(new Category(24), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(400), new Reg(401), new Reg(402)))))),
new Vehical(new Category(25), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(500), new Reg(501), new Reg(502)))))),
new Vehical(new Category(26), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(600), new Reg(601), new Reg(602)))))),
new Vehical(new Category(26), Lists.newArrayList(new Brand(new Model(Lists.newArrayList(new Reg(700), new Reg(701), new Reg(702))))))
);
}

假设我有实体类 TableColumnInfo

public class TableColumnInfo {
@Column(name = "table_name")
private String tableName;
@Column(name = "column_name")
private String columnName;
@Column(name = "data_type")
private String dataType;
@Column(name = "is_nullable")
private Boolean isNullable;
@Column(name = "column_default")
private String columnDefault;
}

在输入中,我得到了如下对象列表:

List<TableColumnInfo> tableColumnInfoRes = some database repository call;

在输出中,我想要嵌套的 MAP,如下所示:

Map<String, Map<String, TableColumnInfo>>

其中

  1. 外映射键:字符串,即表名
  2. 外侧地图值:地图
  3. 内部映射键:字符串,即列名称
  4. 内部映射值:对象,即表列信息

约束条件

  1. 外部映射表名称和内部映射列名称必须属于同一对象。
  2. 这意味着,对于外部映射中的每个表名,内部映射必须具有列名作为键,整个对象作为值(1:1映射(

解决方案: 使用 Java 函数式编程和集合

下面用于生成内部映射的双函数

BiFunction<List<TableColumnInfo>, String, Map<String, TableColumnInfo>> mapper1 =
(infoList, tableName2) ->
{ Map<String, TableColumnInfo> res =
infoList.stream().filter(infoList2 -> infoList2.getTableName().equals(tableName2))
.collect(Collectors.toMap(TableColumnInfo::getColumnName, Function.identity()));
return res;
};

以下用于生成外部映射的代码

Map<String, Map<String, TableColumnInfo>> tableColumnMap = tableColumnInfoRes.stream()
.collect(Collectors.toMap(
tableInfo -> tableInfo.getTableName(),
tableInfo -> mapper1.apply(tableColumnInfoRes,tableInfo.getTableName()),
(a,b)->b
));
  • 在上面的代码中,为每个表名调用 BIFunction。
  • 在 Inner Map 中,要生成值作为对象,请使用 Function.identity((
  • 对于外映射,为避免键冲突,请使用 (a,b( -> b
  • 在 BiFunction 中使用流上的过滤器满足约束。

相关内容

  • 没有找到相关文章

最新更新