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