我曾多次遇到这种情况,希望将多个对象存储在 Map 而不是 Set 或 List 中,因为有一些优势 使用对象的唯一标识信息的Map。 Java 8 通过流和 Collectors.toMap(…) 方法使这种转换比以往任何时候都更容易。
使用 Map
而不是 Set
的一种情况是在处理缺少或具有粗略 equals(Object) 或 hashCode() 实现,但确实有一个唯一标识对象的字段。在那些情况下,如果我不能添加或修复对象的底层实现,我可以通过使用类的唯一标识字段(键)的 Map
到类的实例化对象(价值)。当我更喜欢 Map
而不是 List
或 Set
时,可能更常见的情况是我需要通过特定的唯一标识字段查找集合中的项目.在唯一标识键上进行映射查找速度很快,而且通常比依赖迭代和比较每个对象调用 equals(Object)
方法快得多。
使用 JDK 8,从现有的 Map
或 List
构建 Set
比以往任何时候都容易。为了帮助演示这一点,将使用一个简单的 Book
类。此 Book
类不会覆盖 equals(Object)
类中的 hashCode()
或 Object
,因此不是适合使用的类在 Set
中或作为 Map
键。但是,它的 getIsbn()
方法会返回一个 International Standard Book Number,在本演示中假定该编号是唯一的。
Book.java
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
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
或数组的 stream,所有这三种实现都是相同的。在所有这三种情况下,这只是使用 stream 的 collect() 方法之一的问题(一个 reduction operator 通常是 < span>优于顺序迭代),并向其传递 Collector 接口的实现,该实现是通过来自 Collectors 的预定义 toMap() 收集器提供的类。
针对 Book
的实例运行此演示类的输出如下所示:
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
或数组。尽管在 Java 中将这些 Set
、List
和数组转换为 Map
从来都不是特别困难,但在 Java 中却比以往任何时候都容易8 进行此转换。
标签2: Java教程地址:https://www.cundage.com/article/jcg-converting-collections-maps-jdk-8.html