2

While creating a Map on a stream, I want to insert the values in the same object list for duplicate Keys.
I used Collectors.toMap(keyMapper, valueMapper, mergeFunction).
But I’m unable to write a correct merge function for the same keys.

Here is a working example code to show the exact problem.

Create a Java file named MapCollector and add the below code.

public class MapCollector {
 public static Map<ItemType, ItemRequest> breakRequestByItemType(final ItemRequest originalRequest) {
 return originalRequest
 .getItemStatuses()
 .stream()
 .filter(e->e.getType()!= null)
 .collect(Collectors.toMap(
 ItemStatus::getType,
 e->ItemRequest
 .builder()
 .prop1(originalRequest.prop1)
 .prop2(originalRequest.prop2)
 .itemStatuses(Arrays.asList(e))
 .build()
 //TODO: Need a merge function that will add this status to the list `itemStatuses` 
 ));
 }
}
@Data
@Builder
class ItemRequest{
 List<ItemStatus> itemStatuses;
 String prop1;
 String prop2;
}
enum ItemType{
 A,B,C
}
@AllArgsConstructor
@Getter
enum ItemStatus{
 A_STATUS_1("some desc1",ItemType.A),
 A_STATUS_2("some desc2",ItemType.A),
 B_STATUS_1("some desc3",ItemType.B),
 B_STATUS_2("some desc4",ItemType.B),
 C_STATUS_1("some desc5",ItemType.C);
 private final String desc;
 private final ItemType type;
}

Add the following dependencies in pom.xml for less verbose test code

 <dependencies>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.18.24</version>
 </dependency>
 <dependency>
 <groupId>org.junit.jupiter</groupId>
 <artifactId>junit-jupiter</artifactId>
 <version>5.8.2</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.assertj</groupId>
 <artifactId>assertj-core</artifactId>
 <version>3.21.0</version>
 </dependency>
 </dependencies>

This is the test class showing the expected & test values

public class MapCollectorTest {
 @Test
 void testIt(){
 final ItemRequest originalRequest = ItemRequest.builder()
 .itemStatuses(Arrays.asList(ItemStatus.A_STATUS_1,
 ItemStatus.C_STATUS_1,
 ItemStatus.B_STATUS_2,
 ItemStatus.A_STATUS_2))
 .prop1("abc")
 .prop2("bcd")
 .build();
 Map<ItemType, ItemRequest> expectedMap = new HashMap<ItemType, ItemRequest>();
 expectedMap.put(ItemType.A, ItemRequest
 .builder()
 .itemStatuses(Arrays.asList(ItemStatus.A_STATUS_1,ItemStatus.A_STATUS_2))
 .prop1("abc")
 .prop2("bcd")
 .build());
 expectedMap.put(ItemType.B, ItemRequest
 .builder()
 .itemStatuses(Arrays.asList(ItemStatus.B_STATUS_1))
 .prop1("abc")
 .prop2("bcd")
 .build());
 expectedMap.put(ItemType.C, ItemRequest
 .builder()
 .itemStatuses(Arrays.asList(ItemStatus.C_STATUS_1))
 .prop1("abc")
 .prop2("bcd")
 .build());
 Assertions.assertThat(MapCollector.breakRequestByItemType(originalRequest))
 .containsAllEntriesOf(expectedMap);
 }
}
Alexander Ivanchenko
29.2k6 gold badges29 silver badges53 bronze badges
asked Nov 9, 2022 at 13:47

1 Answer 1

3

//TODO: Need a merge function that will add this status to the list itemStatuses

A merge function of toMap is a BinaryOperator which expects two arguments which are Values associated with the same Key, which should be resolved into a single value returned by the merge function.

A quote from the documentation:

mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)

You need to extract a list itemStatuses from both values and combine them together using Collection.addAll, then return a value whose list has been modified.

(left, right) -> {
 left.getItemStatuses().addAll(right.getItemStatuses());
 return left;
}
answered Nov 9, 2022 at 14:04

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.