java8新特性之toMap的用法——全网独一无二的通俗易懂的讲解

梦想不抛弃苦心追求的人,只要不停止追求,你们会沐浴在梦想的光辉之中。再美好的梦想与目标,再完美的计划和方案,如果不能尽快在行动中落实,最终只能是纸上谈兵,空想一番。只要瞄准了大方向,坚持不懈地做下去,才能够扫除挡在梦想前面的障碍,实现美好的人生蓝图。java8新特性之toMap的用法——全网独一无二的通俗易懂的讲解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

对于java8的新特性toMap方法,相信有很多人都在工作中用过,接下来就通俗易懂的讲解一下toMap吧

先来看看官网对于toMap方法的解释
toMap有个三个重载的方法,每一个重载方法的详解分别如下

(1)方法1:两个参数

public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}

(2)方法2:三个参数

public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,
BinaryOperator mergeFunction)
{
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

(3)方法3:四个参数

public 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 mergeFunction,Supplier mapSupplier)

{
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}

对于上述三个方法中每个参数做下解释
keyMapper:Key 的映射函数
valueMapper:Value 的映射函数
mergeFunction:当 Key 冲突时,调用的合并方法
mapSupplier:Map 构造器,在需要返回特定的 Map 时使用

补充一个重要的知识点,接下来讲解时会依照这个规则讲解

针对于Map集合,在执行put方法时
map.put(k1,v1);
map.put(k1,v2);
最终集合中保留下来的元素是[k1,v2]
总结:每次往Map集合put添加相同的key值时,后面的key对应的value会覆盖前面的那个key对应的value值。


官网看完了接下来开始进行针对性通俗易懂的解释
(1)针对于两个参数的toMap方法,这里简写为toMap(key,value);
循环执行toMap方法的执行的效果相当于

Map map=new HashMap();
for(循环条件) {
if(map.containsKey(oldKey)){
throw new RuntimeException(“xxxxxx”);
}
map.put(key,value);
}
解析:在执行toMap方法在收集元素时,如果遇到了重复的key时,它无法解决这个冲突,即此时会报错。
即如果在循环执行toMap方法,并且往map集合插入重复的key时,默认会报错,具体原因可参考源码。

实践案例:
定义一个User(name=zs,age=23,idNumer=13245906)对象,它有三个属性,

1> Map<String,Integer> map=userList.stream().collect(Collectors.toMap(u->u.getName,u->getAge));
用于收集user类的name与age属性,并且将以key-value键值对的方式插入到map集合中
.
2>Map<String,User> map=userList.stream().collect(Collectors.toMap(u->u.getName,u->u));
用于收集user类的name与User类的对象,并且将key-value键值对的方式插入到map集合中
.
3>Map<String,User> map=userList.stream().collect(Collectors.toMap(u->u.getName,Function.identity()));
用于收集user类的name与User类的对象,并且将key-value键值对的方式插入到map集合中。

注意:这里的Function.identity()是对传入一个对象,并原封不动的返回的是个简法。
在这里插入图片描述
总结:使用这种toMap方法在收集元素时,如果存在重复的Key值时,在收集的过程中会发生冲突,直接导致的后果就是报错。如果想要解决冲突,请参考第二种方法


(2)针对于三个参数的toMap方法,这里简写为两种方式
方式1:toMap(key,value,(k1,k2)->k1);
方式2:toMap(key,value,(k1,k2)->k2);
这两种方式看上去没多大区别,但是意义上却大相径庭,来看看分解后的效果讲解吧

方式1:循环执行toMap方法的执行的效果相当于

Map map=new HashMap();
for(循环条件) {
if(!map.containsKey(oldKey)){
map.put(key,value);
}
}
总结:方式1中的toMap方法在收集元素时,如果遇到了重复的key时,它会放弃收集后面的那个key对应的元素。(k1,k2)->k1就表示k1==k2相同时,保留前面的k1对应的那个键值对,放弃k2对应的那个键值对。

方式2:循环执行toMap方法的执行的效果相当于

Map map=new HashMap();
for(循环条件) {
map.put(key,value);
}
总结:方式1中的toMap方法在收集元素时,如果遇到了重复的key时,它会放弃收集前面的那个key对应的元素。(k1,k2)->k2就表示k1==k2相同时,保留后面最新收集的k2对应的那个键值对,放弃以前收集过的k1对应的那个键值对。

实践案例:
定义一个User(name=zs,age=23,idNumer=13245906)对象,它有三个属性

方式1
Map<String,Integer> map=userList.stream().collect(Collectors.toMap(u->u.getName,u->u.getAge,(k1,k2)->k1));
用于收集user类的name与age属性,并且将以key-value键值对的方式插入到map集合中.
如果在收集过程中发现重名的name值,则保留原先集合中存在的那个key及其对应的value值。舍弃最新待收集的key及其对应的value
.
方式2
Map<String,Integer> map=userList.stream().collect(Collectors.toMap(u->u.getName,u->u.getAge,(k1,k2)->k2));
用于收集user类的name与age属性,并且将以key-value键值对的方式插入到map集合中.
如果在收集过程中发现重名的name值,则舍弃原先集合中存在的那个key及其对应的value值。保留最新待收集的key及其对应的value


(3)针对于四个参数的toMap方法,这里简写为多种方式
方式1:toMap(key,value,(k1,k2)->k1,HashMap::New);
toMap(key,value,(k1,k2)->k2,HashMap::New);
方式2:toMap(key,value,(k1,k2)->k1,TreeMap::New);
toMap(key,value,(k1,k2)->k2,TreeMap::New);
可以对收集到TreeMap集合中的元素按照相应的排序规则进行排序
方式3:toMap(key,value,(k1,k2)->k1,LinkedHashMap::New);
toMap(key,value,(k1,k2)->k2,LinkedHashMap::New);
可以保证收集到LinkedHashMap集合中的元素依旧保持原来的顺序

实践举例:这三种方式其实没多大区别,我们拿其中一个方式举例

针对方式3的toMap(key,value,(k1,k2)->k2,LinkedHashMap::New); 你可以这样理解。
Map map=new LinkedHashMap();
for(循环条件) {
map.put(key,value);
}
解析:在执行toMap方法在收集元素时,创建一个LinkedHashMap集合,然后使用该集合来收集元素,其余的效果同toMap(key,value,(k1,k2)->k2);一样。

经过刚刚的举例讲解,其实也能大概理解这种方式的含义了,它就是在执行toMap方法时构建一个自定义的Map容器,然后循环执行toMap方法时往集合里收集元素,所以该系列方法同三个参数的toMap方法原理几乎一摸一样。

默认情况下,toMap(key,value)与toMap(key,value,(k1,k2)->k1);方法在收集元素时都是构建的一个HashMap容器,然后使用HashMap容器去存储元素,但是HashMap集合我们都知道它是无序的,且无法针对集合中的元素进行排序。所以如果你在工作中有需要针对集合元素进行排序的需求时请使用四个参数的toMap方法.构建一个LinkedHashMap集合可以保证收集的数据依旧保持原来的顺序

总结
(1)toMap(key,value),创建一个HashMap集合用于收集元素,当在收集时出现了重复的key值,它会直接报错,并且中断收集元素到HashMap集合

(2)toMap(key,value,(k1,k2)->k1)创建一个HashMap集合用于收集元素,当在收集时出现了重复的key值时,它会根据(k1,k2)->k1)或者(k1,k2)->k2)这两种规则解决key值重复的冲突并收集元素到HashMap集合

(3) toMap(key,value,(k1,k2)->k2,LinkedHashMap::New)
创建一个LinkedHashMap集合用于收集元素,当在收集时出现了重复的key值时,它会根据(k1,k2)->k1)或者(k1,k2)->k2)这两种规则解决key值重复的冲突并收集元素到LinkedHashMap集合。这种方式的最大好处是可以自定义一个Map集合用于收集元素。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/150498.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!