I'm converting the following list of objects structure to a HashMap using two for loops as shown below.
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);
}
}
How can I do the same thing using lambdas/streams? I tried with a flatMap, but it didn't work. Couldn't access the nested RegId while streaming.
Also, I tried with forEach but finally it looks likes the same for loop solution.
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);
});
Any help would be appreciated.
UPDATE Working code sample based on @Nidhish Krishnan answer
Try this out
If you want to get the result based on grouping, try this one
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));
If you don't want to use grouping try the below one
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));
Not sure what data you are having for vehicalList
, this is how I created the test 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))))))
);
}