![Java核心技术·卷Ⅱ:高级特性(原书第10版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/937/34339937/b_34339937.jpg)
1.9 收集到映射表中
假设我们有一个Stream<Person>,并且想要将其元素收集到一个映射表中,这样后续就可以通过它们的ID来查找人员了。Collectors.toMap方法有两个函数引元,它们用来产生映射表的键和值。例如,
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/019-i.jpg?sign=1738959266-MbY27z5fSrh8ceaagLVBvMxTHxHyQPOH-0-fbccf52754274a359271bc909b1616a0)
在通常情况下,值应该是实际的元素,因此第二个函数可以使用Function.identity()。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/019-2-i.jpg?sign=1738959266-dldHyEmIjGbeheelYvhT22HgMUIPDfk5-0-3c411285770b2e7e48a5e3e6dc5ecaf4)
如果有多个元素具有相同的键,那么就会存在冲突,收集器将会抛出一个Illegal-StateException对象。可以通过提供第3个函数引元来覆盖这种行为,该函数会针对给定的已有值和新值来解决冲突并确定键对应的值。这个函数应该返回已有值、新值或它们的组合。
在下面的代码中,我们构建了一个映射表,存储了所有可用Locale中的每种语言,它在默认Locale中的名字(例如“German”)为键,而其本地化的名字(例如“Deutsch”)为值:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/020-i.jpg?sign=1738959266-DLsf8SYfm6MHsd0uNt9U0CS2ElOcwGT1-0-2f306ee623ebc4eda9523c9bf6fdf2fe)
我们不关心同一种语言是否可能会出现2次(例如,德国和瑞士都使用德语),因此我们只记录第一项。
注意:在本章中,我们使用Locale类作为感兴趣的数据集的数据源。请参阅第7章以了解有关Locale的更多信息。
现在,假设我们想要了解给定国家的所有语言,这样我们就需要一个Map<String,Set<String>>。例如,“Switzerland”的值是集[French,German,Italian]。首先,我们为每种语言都存储一个单例集。无论何时,只要找到了给定国家的新语言,我们都会将已有集和新集做并操作。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/020-2-i.jpg?sign=1738959266-AlRBrIXZ7Tb4EQhoWYaVLo7pjdM3MpWa-0-8feb1b7dc0a1aa72bbbf2cb1bc353224)
在下一节中,你将会看到一种更简单的用于获取这种映射表的方式。
如果想要得到TreeMap,那么可以将构造器作为第4个引元来提供。你必须提供一种合并函数。下面是本节一开始所列举的示例之一,现在它会产生一个TreeMap:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/020-3-i.jpg?sign=1738959266-YPhoJXcxVl0htfOR4d7ymlCJ9aWGUUFd-0-2f5266ea10a4453bd0e889218b50ce72)
注意:对于每一个toMap方法,都有一个等价的可以产生并发映射表的toConcurrentMap方法。单个并发映射表可以用于并行集合处理。当使用并行流时,共享的映射表比合并映射表要更高效。注意,元素不再是按照流中的顺序收集的,但是通常这不会有什么问题。
程序清单1-5中的示例程序给出了将流的结果收集到映射表中的示例。
程序清单1-5 collectin/CollectingIntoMaps.java
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/021-i.jpg?sign=1738959266-STMwOKh4dmPS2UNgvVPoj9LOkepC9sv8-0-023cb3bb98dc3f30bcd3419fc7cbd51e)
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/022-i.jpg?sign=1738959266-RUhv9x76tQ5eU2qIdsqerSTE1lrbWh3g-0-f3623898b3d5c556817d2bd9a5e418b2)
java.util.stream.Collector 8
·static<T,K,U>Collector<T,?,Map<K,U>>toMap(Function<?superT,?extendsK>keyMapper,Function<?super T,?extends U>valueMapper)
·static<T,K,U>Collector<T,?,Map<K,U>>toMap(Function<?superT,?extendsK>keyMapper,Function<?super T,?extends U>valueMapper,BinaryOperator<U>mergeFunction)
·static<T,K,U,M extends Map<K,U>>Collector<T,?,M>toMap(Function<?super T,?extends K>keyMapper,Function<?super T,?extends U>valueMapper,BinaryOperator<U>mergeFunction,Supplier<M>mapSupplier)
·static<T,K,U>Collector<T,?,ConcurrentMap<K,U>>toConcurrentMap(Function<?super T,?extends K>keyMapper,Function<?super T,?extends U>valueMapper)
·static<T,K,U>Collector<T,?,ConcurrentMap<K,U>>toConcurrentMap(Function<?super T,?extends K>keyMapper,Function<?super T,?extends U>valueMapper,BinaryOperator<U>mergeFunction)
·static<T,K,U,M extends ConcurrentMap<K,U>>Collector<T,?,M>toConcurrentMap(Function<?super T,?extends K>keyMapper,Function<?super T,?extends U>valueMapper,BinaryOperator<U>mergeFunction,Supplier<M>mapSupplier)
产生一个收集器,它会产生一个映射表或并发映射表。keyMapper和valueMapper函数会应用于每个收集到的元素上,从而在所产生的映射表中生成一个键/值项。默认情况下,当两个元素产生相同的键时,会抛出一个IllegalStateException异常。你可以提供一个mergeFunction来合并具有相同键的值。默认情况下,其结果是一个HashMap或ConcurrentHashMap。你可以提供一个mapSupplier,它会产生所期望的映射表实例。