1. 介绍

在本教程中,我们将讨论Collectors类的toMap()方法。我们使用它将流收集到一个Map实例中。

对于本教程中涉及的所有示例,我们将使用图书列表作为数据源,并将其转换为不同的Map实现。

2. List 转换 Map

我们将从最简单的情况开始,将List 转换 Map

Book类定义如下:

class Book {
private String name;
private int releaseYear;
private String isbn;
//getters and setters
}
复制代码

接着,我们将创建一个List<Book>来验证我们的代码:

List<Book> bookList = new ArrayList<>();
bookList.add(new Book("The Fellowship of the Ring", 1954, "0395489318"));
bookList.add(new Book("The Two Towers", 1954, "0345339711"));
bookList.add(new Book("The Return of the King", 1955, "0618129111"));
复制代码

对于这个场景,我们将使用以下重载的toMap()方法:

Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper)
复制代码

使用Collectors.toMap(), 我们将会得到一个Map<String,String>,其中key是isbn的值,value为name的值。

public Map<String, String> listToMap(List<Book> books) {
return books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName));
}
复制代码

我们使用单元测试来验证一下代码:

@Test
public void whenConvertFromListToMap() {
assertTrue(convertToMap.listToMap(bookList).size() == 3);//true
}
复制代码

3. 解决 Key 的冲突

上面的例子运行得很好,但是如果有一个重复的key会发生什么呢?

让我们来想象一下,我们将每本图书的出版年份作为key,转换到Map<Integer, Book>中。

public Map<Integer, Book> listToMapWithDupKeyError(List<Book> books) {
return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity()));
}
复制代码

鉴于我们上面的例子,我们会看到一个IllegalStateException的异常:

@Test(expected = IllegalStateException.class)
public void whenMapHasDuplicateKey_without_merge_function_then_runtime_exception() {
convertToMap.listToMapWithDupKeyError(bookList);
}
复制代码

要解决这个问题,我们需要使用另一种toMap()方法,附加一个参数,mergeFunction:

Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
复制代码

让我们引入一个merge函数,它表明,在发生冲突的情况下,我们保留现有的元素:

public Map<Integer, Book> listToMapWithDupKey(List<Book> books) {
return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(),
(existing, replacement) -> existing));
}
复制代码

或者,换句话说,我们获得了未发生异常的元素:

@Test
public void whenMapHasDuplicateKeyThenMergeFunctionHandlesCollision() {
Map<Integer, Book> booksByYear = convertToMap.listToMapWithDupKey(bookList);
assertEquals(2, booksByYear.size());
assertEquals("0395489318", booksByYear.get(1954).getIsbn());
}
复制代码

4. 其他Map类型

默认情况下,toMap()方法将返回一个HashMap。 但是我们也可以返回不同的Map实现。

Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier)
复制代码

其中mapSupplier是一个函数,它返回一个新的、带有结果的空Map

4.1. List 转换 ConcurrentMap

让我们以上面的例子为例,添加一个mapSupplier函数来返回一个ConcurrentHashMap:

public Map<Integer, Book> listToConcurrentMap(List<Book> books) {
return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(),
(o1, o2) -> o1, ConcurrentHashMap::new));
}
复制代码

下面我们测试一下

@Test
public void whenCreateConcurrentHashMap() {
assertTrue(convertToMap.listToConcurrentMap(bookList) instanceof ConcurrentHashMap);
}
复制代码

4.2. List 转换 SortedMap

最后,让我们看看如何返回一个排序后的Map。为此,我们需要对List<Book>进行排序,并使用TreeMap作为mapSupplier参数:

public TreeMap<String, Book> listToSortedMap(List<Book> books) {
return books.stream()
.sorted(Comparator.comparing(Book::getName))
.collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
}
复制代码

上面的代码将List<Book>按照书名进行排序,然后将结果收集到TreeMap<String, Book>中:

@Test
public void whenMapisSorted() {
assertTrue(convertToMap.listToSortedMap(bookList).firstKey().equals("The Fellowship of the Ring"));
}
复制代码

5. 结论

在本文中,我们研究了Collectors类的toMap()方法。它允许我们从一个流创建一个新的Map。我们还学习了如何解决key冲突和创建不同的Map实现。

代码可以在GitHub中找到。

原文链接:www.baeldung.com/java-collec…

作者:Rodrigo Graciano

译者:李东

作者:锅外的大佬
链接:https://juejin.im/post/5d06f11b5188252a71629c7b
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Java 8 Collectors to Map的更多相关文章

  1. Java 8 – Filter a Map examples

    Java 8 – Filter a Map examplesFew Java examples to show you how to filter a Map with Java 8 stream A ...

  2. Java集合框架之map

    Java集合框架之map. Map的主要实现类有HashMap,LinkedHashMap,TreeMap,等等.具体可参阅API文档. 其中HashMap是无序排序. LinkedHashMap是自 ...

  3. Java中如何遍历Map对象的4种方法

    在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHa ...

  4. JAVA的容器---List,Map,Set (转)

    JAVA的容器---List,Map,Set Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashM ...

  5. 转!! Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  6. Java 集合系列 15 Map总结

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  7. Java 集合系列 08 Map架构

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. 【转】Java中如何遍历Map对

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  9. 【转】Java中如何遍历Map对象的4种方法

    原文网址:http://blog.csdn.net/tjcyjd/article/details/11111401 在Java中如何遍历Map对象 How to Iterate Over a Map ...

随机推荐

  1. 【10】react 之 react-router

    1.1.  路由 路由:URL与处理器的映射. 浏览器当前的 URL 发生变化时,路由系统会做出一些响应,用来保证用户界面与 URL 的同步. 1.2.  Router安装 npm i react-r ...

  2. hdu 2189 dp

    /* 类似完全背包,容量为n的背包用素数填,求满背包的种数 dp(i,j)表示用不超过i的素数组成的j的种数 dp[i][j]=dp[i-1][j],若i为素数则dp[i][j]+=dp[i][j-i ...

  3. .NET抓取数据范例 抓取页面上所有的链接

    原文发布时间为:2009-11-15 -- 来源于本人的百度文章 [由搬家工具导入] .NET抓取数据范例 抓取页面上所有的链接 前台: <%@ Page Language="C#&q ...

  4. jQuery 拖动排序

    原文发布时间为:2010-04-11 -- 来源于本人的百度文章 [由搬家工具导入] <!DOCTYPE html><html lang="en">< ...

  5. 拖动层 拖动div 封装js 貌似不兼容FF,郁闷

    原文发布时间为:2009-12-02 -- 来源于本人的百度文章 [由搬家工具导入] <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tran ...

  6. 【电脑使用经验】怎么查看无线网络中电脑的IP地址?

    1. 2. 3. 4. 5.

  7. Android开发基础(java)14

    Java语言与其他编程语言的最大不同之处在于:java有专门的异常处理机制,实现对各类异常情况进行有效控制. 一.基本概念:异常和错误的区别与联系: (1).定义形式不同:异常为exception:错 ...

  8. ext2/3/4的inode结构说明

    系统环境:Ubuntu15.10/ext4 今天在复习<鸟哥的私房菜-基础学习篇>,看到inode大小为128bytes,想看下这128字节里面到底是什么样的. 于是我查了下google, ...

  9. angular6安装

    中文 https://www.angular.cn/ 二.下载 1.安装 node.js https://nodejs.org/en/ 2.删除老angular-cli npm uninstall - ...

  10. (6)ASP.NET HttpServerUtility 类

    HttpServerUtility 类 提供用于处理 Web 请求的 Helper 方法 https://msdn.microsoft.com/zh-cn/library/system.web.htt ...