Search code examples
java-8java-streamcollect

Java 8 stream map custom function and convert it to Map


I have the following object:

public class Book {

    private Long id;
    private Long bookId;
    private String bookName;
    private String owner;
}

Represented from following table: enter image description here

Basically, a book can be owned by multiple owners i.e. Owner "a" owns books 1 and 2.

I have a basic function that will when passed a book object, will give its owner(s) in a List.

private List<String> getBookToOwner(Book book) {
        List<String> a = new ArrayList<>();
        if (book.getOwner() != null && !book.getOwner().isEmpty()) {
            a.addAll(Arrays.asList(book.getOwner().split("/")));
        }
        return a;
}

I want to use that to apply to each book, retrieve their owners and create the following Map.

Map<String, List<Long>> ownerToBookMap;

Like this:

enter image description here

How do I use streams here?

//books is List<Book>
Map<String, List<Long>> ownerToBookMap = books.stream().map( 
// apply the above function to get its owners, flatten it and finally collect it to get the above Map object
// Need some help here..
);

Solution

  • You can get the owner list from the book, then flatten the owners and map as pair of bookId and owner using flatMap. Then grouping by owner using groupingBy and collect the list of bookId of owner.

    Map<String, List<Long>> ownerToBookMap = 
         books.stream()
              .flatMap(b -> getBookToOwner(b)
                             .stream()
                             .map(o -> new AbstractMap.SimpleEntry<>(o, b.getBookId())))
              .collect(Collectors.groupingBy(Map.Entry::getKey,
                         Collectors.mapping(Map.Entry::getValue, Collectors.toList())));