Jay
Jay

Reputation: 9509

Using Collectors.toMap how to convert the map values

I have a Map<String, List<StartingMaterial>> I want to convert the Object in the List to another Object. ie. Map<String, List<StartingMaterialResponse>>

Can I do this using java stream Collectors.toMap()?

I tried something like the below code.

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

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

And my conversion code to change the Object is like below,

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());
}

Upvotes: 2

Views: 10490

Answers (3)

user1234SI.
user1234SI.

Reputation: 1869

Here is my approach to this problem :

    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());
    });

The above example convert the List<Integer> to a list of Strings. In your example, instead of myIntegerProduct.toString() is the convertStartingMaterialToDto method.

The forEach method iterates through every Key-Value pair in the map and you set some names for the key and the value parameters to be more specific and keep an understandable code for everyone who reads it. In my example : forEach( (depositName, products)) -> the depositName is the Key ( in my case a String ) and the products is the Value of the key ( in my case is a List of integers ).

Finally you iterate through the list too and map every item to a new type

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

Upvotes: 1

Youcef LAIDANI
Youcef LAIDANI

Reputation: 60045

I think you mean to do :

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

Upvotes: 1

Ravindra Ranwala
Ravindra Ranwala

Reputation: 21124

You can use the toMap collector since your source is a map. However you have to iterate over all the values and convert each of them into the DTO format inside the 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())));

Upvotes: 2

Related Questions