Как создать список <T>на картувместо карты? - PullRequest
0 голосов
/ 11 февраля 2019

Я сталкивался со случаем, когда мне нужно преобразовать List<Book> в Map<String, Book>, и единственное решение, которое я могу найти, это как Map<String, List<Book>>.

Сам класс выглядит следующим образом (япропущенные геттеры / сеттеры и конструкторы):

public class Book {
    private String asin;
    private String author;
    private String title;
}

Я хочу отобразить все книги по определенным уникальным ключам, поэтому вероятность дублирования либо пренебрежимо мала, либо 0.

Я пытался сделатьэто так:

    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)));

Это работает, но выглядит некрасиво, трудно читаемо и не очень приятно иметь в базе кода, потому что это может смутить моих коллег.Есть ли лучший способ java 8 добиться того же результата?

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Используйте toMap вместо groupingBy:

Map<String, Book> booksByAsinAndTitle = 
    books.stream()
         .collect(Collectors.toMap(b -> b.getAsin() + "||" + b.getTitle(),
                                   Function.identity()));

Если ключ, по которому вы группируете, является уникальным, нет смысла использовать groupingBy.

ЕслиВаш ключ может быть не уникальным, и вы все же хотите, чтобы Map содержал первое значение, соответствующее данному ключу, добавьте функцию слияния:

Map<String, Book> booksByAsinAndTitle = 
    books.stream()
         .collect(Collectors.toMap(b -> b.getAsin() + "||" + b.getTitle(),
                                   Function.identity()),
                                   (a,b) -> a);
0 голосов
/ 11 февраля 2019

Более простое представление того же самого с использованием Map.putIfAbsent и forEach будет:

Function<Book, String> primaryKey = book -> book.getAsin() + "||" + book.getTitle();
Map<String, Book> booksByAsinAndTitle = new HashMap<>();
books.forEach(book -> booksByAsinAndTitle.putIfAbsent(primaryKey.apply(book), book));

Примечание : Этогарантирует, что первый book найденный против ключа останется на карте.

0 голосов
/ 11 февраля 2019

Вам не нужно группировать свои книги, если вы уверены, что ключи уникальны.

Map<String, Book> booksByAsinAndTitle = books.stream()
    .collect(Collectors.toMap(book -> book.getAsin() + "||" + book.getTitle(), x -> x));
...