博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈lambda表达式-Collectors.toMap
阅读量:4038 次
发布时间:2019-05-24

本文共 3441 字,大约阅读时间需要 11 分钟。

jdk自从8开始,添加了lambda表达式,为了兼容lambda表达式,所以对接口也做了修改,添加了default关键词。这是jdk8与7最大的一个变动。

自从有了lambda表达式之后,项目中被大量运用,但是对于我本人来讲,我其实是挺反对用lambda表达式的,我也一直不用它。原因有三:

其一,就是它虽然让代码变的简洁,但是简洁的结果就是造成语法并不为常人理解,我觉得它的语法上并不是通俗易懂的,需要翻看说明才能看的懂;

其二,没法调试,它采用流的方式进行处理,内存的逻辑根本没法调试;

其三,性能方面,对于数据量少,并发量不大的情况下,我觉得性能很差,这个文章后面也会简单的做下比较。有人说高并发大数据量会有性能优势,但是并发量要大到什么程度,数据量要大到什么程度,没有验证过。而且我们实际工作中,不会一次性处理大量数据,一般都会分页/分批处理。高并发也会进行请求的分发,实际到一台服务器上也不会有很大的并发。

那接下来简单介绍下lambda表达式中使用Collectors.toMap的例子,因为今天review代码的时候刚好注意到它了,就简单研究了下。

这个方法主要是用在我们一个list集合中的元素,要根据一定的条件,将list的集合中的元素内容,放到map集合中。直接上代码吧:

public class TestStream {    public static void main(String[] args) {        List
list = new ArrayList<>(); list.add(new Person("zs","sssss")); list.add(new Person("zs","ddddd")); list.add(new Person("ls","sssss")); list.add(new Person("wk","wwwww")); long time1 = System.currentTimeMillis(); //使用lambda表达式进行处理 Map
resultMap = list.stream().collect(Collectors.toMap(Person::getName, item->item.getAddress(),(a, s)->s+","+a)); long time2 = System.currentTimeMillis(); //使用常规方法处理 Map
result = new HashMap<>(); for(Person p : list){ result.put(p.getName(),result.get(p.getName()) == null? p.getAddress() : result.get(p.getName())+","+p.getAddress()); } long time3 = System.currentTimeMillis(); for(Map.Entry
entry : resultMap.entrySet()){ System.out.println(entry.getKey()+"======="+entry.getValue()); } System.out.println((time2-time1)+"======="+(time3-time2)); for(Map.Entry
entry : result.entrySet()){ System.out.println(entry.getKey()+"======="+entry.getValue()); } }}class Person{ private String name; private String address; public Person(String name, String address){ this.name = name; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }}

简单介绍下代码干了啥。代码中有个Person类,有name和address两个属性。 一个list集合中放了多个person对象,并且person对象有name重复,但是address不一样的记录。

现在要把list中的元素放到一个map集合中,key是name值,value是address值。 对于name重复的,让他们的address值合并到一个name中,用逗号隔开,存到map里。

lambda表达式用了一行就解决了。但是常规方法,用了四行代码。

lambda表达式将list先转化为stream()流,调用collect()方法,参数是个Collector。Collectors提供了很多返回Collector的静态方法,toMap就是其中之一。

toMap有三个参数,第一个是key生成的方法/函数,第二个是value生成的方法/函数,第三个是对于重复key的合并逻辑方法/函数。

对于第一和第二个参数,使用Person::getName() / Person::getAddress()方法也行,使用item->item.getName() / item -> item.getAddress()也行,这是两种方式。item是个代名词,你改成任何字母或者单词(关键词除外)标识都行。

对于第三个参数,(a,s)->a+","+s 这个段代码,是个条件函数,是处理对于重复key的情况下的合并处理逻辑。

其中a,s分别代表重复的两个name对应的address值,a/s只是个标识,你用其他任何字母代替都行,但是a和s是有顺序的,在(a,s)的写法中, a表示list集合中靠前的值,s是靠后的值。如果写成(s,a),那么s就是靠前的值,a就是靠后的值), 所以如果这个函数表达式写成 (a,s)->a ,意思就是如果遇到重复的name(因为map的key是不会重复的),那么map中value的值取排序靠前name对应的address值。 用上面的代码例子来说的话,最后map中key为zs的value值就是sssss。

如果写成(a,s)->s, 也就是如果遇到重复的name,那么map中value的值就是让后面的address覆盖前面的address。用上面的代码例子来说的话,最后map中key为zs的value值就是ddddd。

好了,toMap的介绍就到这里了。下面就看下性能吧。

直接看下我本地运行的例子的打印结果吧:

99是毫秒,也就是lambda表达式这一行,就运行了99ms,但是常规方法,四行运行了0ms。总共才4条数据,耗费了99ms。看到性能了么。99ms,对于一个接口来讲,意味着1秒钟也就支持10个左右的并发。这也是为什么我不太喜欢我们兄弟们使用lambda表达式最主要的原因。

言尽于此,对于jdk自己推出了lambda表达式,那么性能方面他们应该也会考虑去优化,对于朋友们用不用lambda表达式,还是根据自己的实际情况及意愿来吧。

 

 

 

转载地址:http://dhcdi.baihongyu.com/

你可能感兴趣的文章
Java Math的 floor,round和ceil的使用
查看>>
通过url方式传递中文乱码解决办法
查看>>
Java的初始化机制、垃圾回收机制和内存分配机制
查看>>
MySQL5.6安装步骤(windows7/8_64位)
查看>>
FreeMarker基础配置
查看>>
Java中使用Jedis操作Redis
查看>>
Redis中常用命令
查看>>
spring下载
查看>>
读取request流
查看>>
微信消息模板的配置
查看>>
Spring框架结合Quartz实现任务调度实例
查看>>
Quartz Cron表达式 在线生成器
查看>>
struts2中action接收参数的3种方法
查看>>
java获取随机数
查看>>
url中传递中文参数时的转码与解码
查看>>
百度Ueditor设置允许上传的图片格式及大小
查看>>
java图形验证码生成工具类及web页面校验验证码
查看>>
微信菜单的配置
查看>>
移动端的emoji表情符号插入MySQL数据库失败
查看>>
mysql对指定列进行排名
查看>>