我有两个模型,一个 List<ModelA>
我想将其转换为 List<ModelB>
.
这是我的模型:
class ModelA {
private Long id;
private String name;
private Integer value;
public ModelA(Long id, String name, Integer value) {
this.id = id;
this.name = name;
this.value = value;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public Integer getValue() {
return value;
}
}
class ModelB {
private Long id;
private Map<String, Integer> valuesByName;
public ModelB(Long id, Map<String, Integer> valuesByName) {
this.id = id;
this.valuesByName = valuesByName;
}
public Long getId() {
return id;
}
public Map<String, Integer> getValuesByName() {
return valuesByName;
}
}
实际解决方案:
public static List<ModelB> convert(List<ModelA> models) {
List<ModelB> toReturn = new ArrayList<>();
Map<Long, Map<String, Integer>> helper = new HashMap<>();
models.forEach(modelA -> {
helper.computeIfAbsent(modelA.getId(), value -> new HashMap<>())
.computeIfAbsent(modelA.getName(), value -> modelA.getValue());
});
helper.forEach((id, valuesByName) -> toReturn.add(new ModelB(id,valuesByName)));
return toReturn;
}
但我认为有一个更简单的解决方案,您是否知道如何在单个流中完成或以某种方式简化它?
编辑:我想澄清的是,我不能使用 java9,我需要先按 Id-s 然后再按名称对它们进行分组。如果在 ModelB 中我有 4 个具有相同 ID 的元素,我不想要 ModelA 的新实例。
最佳答案
我结合了这两个操作,但仍然构建中间映射,因为您需要为给定的 id group 所有 name, value 对.
models.stream()
.collect(Collectors.groupingBy(model -> model.getId(), //ModelA::getId - Using method reference
Collectors.toMap(model -> model.getName(), model -> model.getValue(), (map1, map2) -> map1)))
.entrySet()
.stream()
.map(entry -> new ModelB(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
编辑:
我在初始答案中错过了 (map1, map2) -> map1
。需要避免为 id
、name
(相当于您的第二个 computeIfAbsent
)覆盖已经存在的 value
在你的代码中)
您需要选择其中之一(或合并它们),因为默认情况下它会在找到重复键时抛出 IllegalStateException
。
关于Java-8:流还是更简单的解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49532138/