Java-8:流还是更简单的解决方案?

Sun*_*ame 6 java java-8 java-stream

我有两个型号,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

实际解决方案

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;
    }
Run Code Online (Sandbox Code Playgroud)

但我认为有一个更简单的解决方案,您是否知道如何在单个流中执行此操作,或以某种方式简化它?

编辑:我想澄清我不能使用java9,我需要通过Id-s然后按名称对它们进行分组.如果在ModelB中我有4个具有相同id的元素,我不想要ModelA的新实例.

use*_*er7 7

我已将两个操作组合在一起,但仍构建中间映射,因为您需要为给定的id 分组所有名称,值对.

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());
Run Code Online (Sandbox Code Playgroud)

编辑:

我错过(map1, map2) -> map1了最初的答案.这是需要避免覆盖已经存在valueid,name(你的第二个相当于computeIfAbsent在你的代码),您需要选择其中一个(或米格它们),因为默认情况下它会抛出IllegalStateException时,发现重复的键.