Статьи

Преобразование коллекций в карты с помощью JDK 8

Я несколько раз сталкивался с ситуацией, когда желательно хранить несколько объектов на карте вместо набора или списка, потому что есть несколько преимуществ от использования карты уникальной идентифицирующей информации для объектов. Java 8 сделала этот перевод проще, чем когда-либо, с помощью потоков и методов Collectors.toMap (…) .

Одна из ситуаций, в которой было полезно использовать Map вместо Set — это при работе с объектами, в которых отсутствуют или имеют схематичные реализации equals (Object) или hashCode () , но есть поле, которое однозначно идентифицирует объекты. В этих случаях, если я не могу добавить или исправить базовые реализации объектов, я могу получить лучшие гарантии уникальности, используя Map уникально идентифицирующего поля класса (ключа) для экземпляра объекта (значения) класса. Возможно, более частый сценарий, когда я предпочитаю Map to List или Set это когда мне нужно искать элементы в коллекции по определенному уникально идентифицирующему полю. Поиск карты по уникально идентифицирующему ключу является быстрым и часто намного быстрее, чем в зависимости от итерации и сравнения каждого объекта с вызовом для метода equals(Object) .

С JDK 8 проще, чем когда-либо, построить Map из существующего List или Set . Чтобы продемонстрировать это, будет использован простой класс Book . Этот класс Book не переопределяет equals(Object) или hashCode() из класса Object и поэтому не является подходящим классом для использования в Set или в качестве ключа Map . Однако его getIsbn() возвращает международный стандартный номер книги, который считается уникальным для этой демонстрации.

Book.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package dustin.examples.jdk8;
 
/**
 * Represents a book, but does not override {@code equals(Object)}
 * or {@code hashCode()}.
 */
public class Book
{
   /** International Standard Book Number (ISBN-13). */
   final String isbn;
 
   /** Title of book. */
   final String title;
 
   /** Edition of book. */
   final int edition;
 
   /**
    * Constructor.
    *
    * @param newIsbn International Standard Book Number (-13).
    * @param newTitle Title.
    * @param newEdition Edition.
    */
   public Book(final String newIsbn, final String newTitle, final int newEdition)
   {
      isbn = newIsbn;
      title = newTitle;
      edition = newEdition;
   }
 
   /**
    * Provide ISBN-13 identifier associated with this book.
    *
    * @return ISBN-13 identifier.
    */
   public String getIsbn()
   {
      return isbn;
   }
 
   /**
    * Provide title of this book.
    *
    * @return Book's title.
    */
   public String getTitle()
   {
      return title;
   }
 
   /**
    * Provide edition of this book.
    *
    * @return Book's edition.
    */
   public int getEdition()
   {
      return edition;
   }
 
   @Override
   public String toString()
   {
      return title + " (Edition " + edition + ") - ISBN-13: " + isbn;
   }
}

С этим классом демонстрационный класс CollectionToMapDemo показывает, насколько просто с JDK 8 легко конвертировать различные типы коллекций Java ( Set , List и даже массивы) в Map .

CollectionToMapDemo.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package dustin.examples.jdk8;
 
import static java.lang.System.out;
 
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
 
/**
 * Demonstrates conversion of Java collections to Java Maps.
 */
public class CollectionToMapDemo
{
   /**
    * Multiple instances of Book, a class that lacks a proper
    * equals(Object) method, but for which its getIsbn() method
    * is assumed to return a unique identifier for each instance.
    */
   private static final Book[] books;
 
   static
   {
      books = new Book[]
         {
            new Book("978-0-201-31005-4", "Effective Java", 1),
            new Book("978-0-321-35668-0", "Effective Java", 2),
            new Book("978-0-13-468599-1", "Effective Java", 3)
         };
   }
 
   /**
    * Convert provided array of Book instances to Map of each Book's ISBN to
    * that instance of the Book.
    *
    * @param booksArray Array of Book instances.
    * @return Map of each book's ISBN (key) to the book's full instance (value).
    */
   private static Map<String, Book> convertArrayToMap(final Book[] booksArray)
   {
      return Arrays.stream(books).collect(
         Collectors.toMap(Book::getIsbn, book -> book));
   }
 
   /**
    * Convert provided List of Book instances to Map of each Book's ISBN to
    * that instance of the Book.
    *
    * @param booksList List of Book instances.
    * @return Map of each book's ISBN (key) to the book's full instance (value).
    */
   private static Map<String, Book> convertListToMap(final List<Book> booksList)
   {
      return booksList.stream().collect(
         Collectors.toMap(Book::getIsbn, book -> book));
   }
 
   /**
    * Convert provided Set of Book instances to Map of each Book's ISBN to
    * that instance of the Book.
    *
    * @param booksSet Set of Book instances.
    * @return Map of each book's ISBN (key) to the book's full instance (value).
    */
   private static Map<String, Book> convertSetToMap(final Set<Book> booksSet)
   {
      return booksSet.stream().collect(
         Collectors.toMap(Book::getIsbn, book -> book));
   }
 
   public static void main(final String[] arguments)
   {
      out.println("ARRAY->MAP:\n" + convertArrayToMap(books));
 
      final List<Book> booksList = Arrays.asList(books);
      out.println("LIST->MAP:\n" + convertListToMap(booksList));
 
      final Set<Book> booksSet
         = new HashSet<>(Arrays.stream(books).collect(Collectors.toSet()));
      out.println("SET->MAP:\n" + convertSetToMap(booksSet));
   }
}

Наиболее важными методами в только что показанном списке классов являются convertArrayToMap(Book[]) , convertListToMap(List<Book>) и convertSetToMap(Set<Book>) . Все три реализации одинаковы, если к потоку на основе базового Set , List или массива был получен доступ. Во всех трех случаях это просто вопрос использования одного из методов collect () потока ( оператор редукции, который обычно предпочтительнее последовательной итерации ) и передачи ему реализации интерфейса Collector, который предоставляется через предопределенный toMap ( ) Коллекционер из класса Коллекционеры .

Результат запуска этого демонстрационного класса для экземпляров Book показан ниже:

1
2
3
4
5
6
ARRAY->MAP:
{978-0-201-31005-4=Effective Java (Edition 1) - ISBN-13: 978-0-201-31005-4, 978-0-321-35668-0=Effective Java (Edition 2) - ISBN-13: 978-0-321-35668-0, 978-0-13-468599-1=Effective Java (Edition 3) - ISBN-13: 978-0-13-468599-1}
LIST->MAP:
{978-0-201-31005-4=Effective Java (Edition 1) - ISBN-13: 978-0-201-31005-4, 978-0-321-35668-0=Effective Java (Edition 2) - ISBN-13: 978-0-321-35668-0, 978-0-13-468599-1=Effective Java (Edition 3) - ISBN-13: 978-0-13-468599-1}
SET->MAP:
{978-0-201-31005-4=Effective Java (Edition 1) - ISBN-13: 978-0-201-31005-4, 978-0-321-35668-0=Effective Java (Edition 2) - ISBN-13: 978-0-321-35668-0, 978-0-13-468599-1=Effective Java (Edition 3) - ISBN-13: 978-0-13-468599-1}

Я сталкивался с несколькими ситуациями, в которых было выгодно иметь несколько объектов в Map уникального идентификатора для полного экземпляра этих объектов, но им были переданы объекты в Set , List или массиве. Хотя никогда не было особенно трудно преобразовать эти Set , List и массивы в Map s в Java, это проще, чем когда-либо в Java 8, чтобы выполнить это преобразование.

Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Преобразование коллекций в карты с JDK 8

Мнения, высказанные участниками Java Code Geeks, являются их собственными.