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. 使用mapMutations扩展写法后参数传递的办法

    在没使用扩展办法的时候,在组件当中通过下面方式进行传参 testMethods(data) { this.$store.commit("add",data) } 而使用了扩展函数了 ...

  2. 游戏(bzoj 1854)

    Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性 ...

  3. pat 甲级 Cars on Campus (30)

    Cars on Campus (30) 时间限制 1000 ms 内存限制 65536 KB 代码长度限制 100 KB 判断程序 Standard  题目描述 Zhejiang University ...

  4. poj 2280 Islands and Bridges 哈密尔顿路 状压dp

    题目链接 题意 给定一个\(N\)个点的无向图,求一条哈密尔顿路径\(C_1C_2...C_n\),使其\(value\)最大. \(value\)的计算方式如下:\[\begin{aligned}v ...

  5. EventBus 3.0: 入门使用及其使用 完全解析

    前言 EventBus是greenrobot再Android平台发布的以订阅-发布模式为核心的开源库. EventBus翻译过来是事件总线意思.可以这样理解:一个个(event)发送到总线上, 然后E ...

  6. Goodbye 2017 B

    [题意]: 鲍勃编程一个机器人在2d迷宫中导航.迷宫有一些障碍.空单元格用'.'表示,其中障碍物用'#'表示.迷宫中有一个机器人.它的起始位置用字符“S”表示.这个位置没有任何障碍.迷宫中也有一个出口 ...

  7. superagent-promise

    var Promise = this.Promise || require('promise'); var agent = require('superagent-promise')(require( ...

  8. 渗透测试集成环境Faraday

    渗透测试集成环境Faraday   Kali Linux集成了海量的渗透测试工具.但是这些工具在使用的时候,还是分离的.虽然用户可以通过Shell.日志/报告导入导出功能等方式,进行整合,但是仍然不便 ...

  9. 某考试 T1 fair (18.5.1版)

    转化一下模型:每天可以选1也可以选0,但是任意前i天(i<=n)1的个数都必须>=0的个数,求总方案数/2^n. 然后可以发现这是一个经典题,随便推一下公式发现等于  C(n,n/2)/2 ...

  10. OpenSSL使用1(用OpenSSL生成自签名证书在IIS上搭建Https站点)(用于iOS的https访问)

    前提: 先安装openssl,安装有两种方式,第一种直接下载安装包,装上就可运行:第二种可以自己下载源码,自己编译.这里推荐第一种. 安装包:http://slproweb.com/products/ ...