I encountered with the case when I need to convert List<Book> to Map<String, Book> and the only solutions I can find is how to do Map<String, List<Book>>.
The class itself looks the following way (I ommitted getters/setters and constructors):
public class Book {
private String asin;
private String author;
private String title;
}
I want to map all books by certain unique keys, so probability of duplication is either neglectable or 0.
I tried to do it this way:
Map<String, Book> booksByAsinAndTitle = books.stream()
.collect(Collectors.groupingBy((book) -> book.getAsin() + "||" + book.getTitle()))
.entrySet()
.stream()
.collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue().get(0)));
It works but it looks ugly, hardly readable and not very nice to have in the codebase because it may confuse my colleagues. Is there any better way java 8 way to achieve the same result?
Use toMap instead of groupingBy:
Map<String, Book> booksByAsinAndTitle =
books.stream()
.collect(Collectors.toMap(b -> b.getAsin() + "||" + b.getTitle(),
Function.identity()));
If the key according to which you are grouping is unique, there's no reason to use groupingBy.
If your key may not be unique, and you still want the Map to contain the first value matching a given key, add a merge function:
Map<String, Book> booksByAsinAndTitle =
books.stream()
.collect(Collectors.toMap(b -> b.getAsin() + "||" + b.getTitle(),
Function.identity()),
(a,b) -> a);
You don't need to group your books if you are sure that the keys are unique.
Map<String, Book> booksByAsinAndTitle = books.stream()
.collect(Collectors.toMap(book -> book.getAsin() + "||" + book.getTitle(), x -> x));
A simpler representation of the same using Map.putIfAbsent and forEach would be :
Function<Book, String> primaryKey = book -> book.getAsin() + "||" + book.getTitle();
Map<String, Book> booksByAsinAndTitle = new HashMap<>();
books.forEach(book -> booksByAsinAndTitle.putIfAbsent(primaryKey.apply(book), book));
Note: This ensures that the first book found against a key remains in the map.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With