Используя Collectors.toMap, как преобразовать значения карты - PullRequest
2 голосов
/ 17 января 2020

У меня есть Map<String, List<StartingMaterial>> Я хочу преобразовать объект в списке в другой объект. ie. Map<String, List<StartingMaterialResponse>>

Могу ли я сделать это, используя java stream Collectors.toMap ()?

Я пробовал что-то вроде приведенного ниже кода.

Map<String, List<StartingMaterial>>  startingMaterialMap = xxxx;

startingMaterialMap.entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, Function.identity(), (k, v) -> convertStartingMaterialToDto(v.getValue())));

И мое преобразование код для изменения объекта, как показано ниже,

private StartingMaterialResponse convertStartingMaterialToDto(StartingMaterial sm) {

    final StartingMaterialMatrix smm = sm.getStartingMaterialMatrix();
    final StartingMaterial blending1Matrix = smm.getBlending1Matrix();
    final StartingMaterial blending2Matrix = smm.getBlending2Matrix();

    return new StartingMaterialResponse(
            sm.getId(),
            sm.getComponent().getCasNumber(),
            sm.getDescription(),
            sm.getPriority(),
            String.join(" : ",
                    Arrays.asList(smm.getCarryInMatrix().getComponent().getMolecularFormula(),
                            blending1Matrix != null ? blending1Matrix.getComponent().getMolecularFormula() : "",
                            blending2Matrix != null ? blending2Matrix.getComponent().getMolecularFormula() : ""
                    ).stream().distinct().filter(m -> !m.equals("")).collect(Collectors.toList())),
            smm.getFamily(),
            smm.getSplitGroup());
}

Ответы [ 3 ]

3 голосов
/ 17 января 2020

Вы можете использовать коллектор toMap, поскольку ваш источник - карта. Однако вам нужно перебрать все значения и преобразовать каждое из них в формат DTO внутри valueMapper.

Map<String, List<StartingMaterialResponse>> result = startingMaterialMap.entrySet().stream()
    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
        .map(s -> convertStartingMaterialToDto(s)).collect(Collectors.toList())));
1 голос
/ 17 января 2020

Вот мой подход к этой проблеме:

    Map<String, List<Integer>> deposits = new HashMap<>();

    deposits.put("first", Arrays.asList(1, 2, 3));

    deposits.forEach((depositName, products) -> {
        products.stream()
                .map(myIntegerProduct -> myIntegerProduct.toString())
                .collect(Collectors.toList());
    });

В приведенном выше примере преобразование List<Integer> в список строк. В вашем примере вместо myIntegerProduct.toString() используется метод convertStartingMaterialToDto.

Метод forEach выполняет итерацию для каждой пары Key-Value на карте и Вы задаете некоторые имена для ключа и параметров-значений, чтобы они были более точными c и оставляли понятный код для всех, кто его читает. В моем примере: forEach( (depositName, products)) -> depositName - это ключ (в моем случае - строка), а products - это значение ключа (в моем случае это список целых чисел). .

Наконец, вы перебираете список и map для каждого элемента нового типа

products.stream() .map(myIntegerProduct -> myIntegerProduct.toString())

1 голос
/ 17 января 2020

Я думаю, что вы хотите сделать:

startingMaterialMap.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                e -> e.getValue().stream()
                        .map(this::convertStartingMaterialToDto)
                        .collect(Collectors.toList()))
        );
...