Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Collect list of objects to set of strings after groupingBy java stream

Given the following classes Order and Item and a list of Orders

@Getter
@AllArgsConstructor
@ToString
public class Order {
    String customerName;
    List<Item> items;
}

@Getter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Item {
    long id;
    String name;
}

I need to create a map Map<String,Set<String>> itemsByCustomerName where keys are customer names from Order and a set of names of all Items belonging to the customer name.

Example input:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

List<Order> orders = List.of(
        new Order("John", List.of(new Item(1, "A"), new Item(2, "B"), new Item(3, "C"))),
        new Order("Alex", List.of(new Item(1, "A"), new Item(8, "H"), new Item(11, "K"))),
        new Order("John", List.of(new Item(1, "A"), new Item(6, "F"), new Item(7, "G"))),
        new Order("Alex", List.of(new Item(1, "A"), new Item(8, "H"), new Item(12, "L"))),
        new Order("Dave", List.of(new Item(24,"X"), new Item(25,"Y"), new Item(26, "Z"))));

the desired output would be

{Alex=[A, H, K, L], John=[A, B, C, F, G], Dave=[X, Y, Z]}

I have tried many ways including my last attempt below, but getting compile errors

Map<String, Set<String>> itemsByCustomerName =
    orders.stream().collect(groupingBy(
            Order::getCustomerName,
            mapping(order -> order.getItems().stream().map(Item::getName), toSet())));

Error:

Required type:
Map<String, Set<String>>
Provided:
Map<String, Set<Object>>

no instance(s) of type variable(s) R exist so that Stream<R> conforms to String inference variable T 
has incompatible bounds: equality constraints: String lower bounds: Stream<R81591>

How can I get instead of just a map of orders by name:

Map<String, List<Order>> ordersByName =
    orders.stream().collect(groupingBy(Order::getCustomerName));

to a Map<String, Set<Item>> or much better Map<String, Set<String>> with a set of item names?

Generally asking: how to convert list of orders to set of strings after groupingBy?

>Solution :

You were very close.

Since you need to transform a stream element not into a single object, but extract a collection of items from the order, you need a different collectorflatMapping() instead of mapping().

Map<String, Set<String>> itemsByCustomerName =
    orders.stream().collect(Collectors.groupingBy(
        Order::getCustomerName,
        Collectors.flatMapping(order -> order.getItems().stream().map(Item::getName),
            Collectors.toSet())));
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading