![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=1738905999-il4xe0B7XBl74yUZgTNAYKhpi0gSqp4I-0-4356d926c83adb7fcc4ae0464a4687eb)
在通常情况下,值应该是实际的元素,因此第二个函数可以使用Function.identity()。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/019-2-i.jpg?sign=1738905999-VfRosd1EoCfeE8ZvybTiEeniriytvPPH-0-5a3214e11f51193bb0d22f27dc567d67)
如果有多个元素具有相同的键,那么就会存在冲突,收集器将会抛出一个Illegal-StateException对象。可以通过提供第3个函数引元来覆盖这种行为,该函数会针对给定的已有值和新值来解决冲突并确定键对应的值。这个函数应该返回已有值、新值或它们的组合。
在下面的代码中,我们构建了一个映射表,存储了所有可用Locale中的每种语言,它在默认Locale中的名字(例如“German”)为键,而其本地化的名字(例如“Deutsch”)为值:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/020-i.jpg?sign=1738905999-kjb6mr2zHldwghRqddIQ5w1CgPUJzQmR-0-e1e04324a3cd2b393f78bcba1e6f7577)
我们不关心同一种语言是否可能会出现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=1738905999-8xrPSbbI5hFoKTnCw4q1ONZN33nvZ3uV-0-59a79d3fcf10490e49e58d64e642c68d)
在下一节中,你将会看到一种更简单的用于获取这种映射表的方式。
如果想要得到TreeMap,那么可以将构造器作为第4个引元来提供。你必须提供一种合并函数。下面是本节一开始所列举的示例之一,现在它会产生一个TreeMap:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/020-3-i.jpg?sign=1738905999-XQVTyP5qDSd89SHQ8WrmdS4AOnG7wlZp-0-4bcfe590546ab5644444964e08cef0b5)
注意:对于每一个toMap方法,都有一个等价的可以产生并发映射表的toConcurrentMap方法。单个并发映射表可以用于并行集合处理。当使用并行流时,共享的映射表比合并映射表要更高效。注意,元素不再是按照流中的顺序收集的,但是通常这不会有什么问题。
程序清单1-5中的示例程序给出了将流的结果收集到映射表中的示例。
程序清单1-5 collectin/CollectingIntoMaps.java
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/021-i.jpg?sign=1738905999-jWJL006tQHoCSAWmXvyMCIOGVrguQcRZ-0-7f79ee97e5cf79ca79d9598ea9cd6084)
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/022-i.jpg?sign=1738905999-ZaiESS1AtLe1dCmaunuBW2btyEx1nnKw-0-1e25636dc24abf03973327a8e1619610)
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,它会产生所期望的映射表实例。