Я несколько раз сталкивался с ситуацией, когда желательно хранить несколько объектов на карте вместо набора или списка, потому что есть несколько преимуществ от использования карты уникальной идентифицирующей информации для объектов. 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, являются их собственными. |