JDK8--02:为什么要使用lambda
lambda是一个匿名函数,我们可以把lambda理解为一个可以传递的代码(将代码像数据一样传递),可以写出更简洁更灵活的代码。
首先看一下原来的匿名内部类实现方式(以比较器为例)
//原来的匿名内部类实现方式
public void test1(){
//定义一个匿名内部类comparator
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
//将匿名内部类作为对象传入
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
以上代码实际上实际有用的代码只有两行(第7行),但是却需要写这么多代码,非常痛苦,lambda就很好的解决了该问题。
lambda实现方式
//lambda表达式实现
public void test2(){
//lambda表达式
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
//将匿名内部类作为对象传入
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
通过以上可以看到,原来的多行代码,变为了一行实现,代码量大大减少,但是,如果只是这样的一个结论,显然不能说服人(匿名内部类我直接就可以一键生成,对开发来说影响并不是很大,反而要学习一个新的语法,这种投入产出比不太大)
所以再举一个例子来说明lambda的优势:
需求1:获取公司中年龄大于35岁的员工
先创建实体类
package com.example.jdk8demo.lambda; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.ToString; @Data
@RequiredArgsConstructor
@AllArgsConstructor
@ToString
public class Employer {
private String name;
private Integer age;
private double salary;
}
为了方便演示,就不再进行数据库操作,直接模拟一个员工集合
/**
* 模拟员工集合
*/
private List<Employer> list = Arrays.asList(
new Employer("张三",,2222.22),
new Employer("李四",,3333.33),
new Employer("王五",,4444.44),
new Employer("赵六",,5555.55),
new Employer("田七",,4235.32),
new Employer("牛八",,3256.52)
);
然后就是实现逻辑代码,我们一般会直接定义一个方法去实现,如下代码所示
/**
* 查询年龄大于35岁的员工
* @return
*/
public List<Employer> getEmpolyerByAge(){
List<Employer> employerList = new ArrayList<>();
for (Employer employer : list){
if(employer.getAge() > ){
employerList.add(employer);
}
}
return employerList;
}
那么如果此时,又来了一个需求
需求2:查询工资大于4000的员工
我们还需要再写一个实现方法
/**
* 查询工资大于4000的员工
* @return
*/
public List<Employer> getEmpolyerBySalary(){
List<Employer> employerList = new ArrayList<>();
for (Employer employer : list){
if(employer.getSalary() > ){
employerList.add(employer);
}
}
return employerList;
}
可以发现,两个方法中,只有 employer.getAge() > 35 和 employer.getSalary() > 4000 是不同的,其余的代码都一样,如果后续还有新的类似需求增加,呢么冗余代码会越来越多,因此我们就需要对代码进行优化。
优化方案一:使用策略模式
一般情况下,对于这种冗余代码,我们的优化会使用策略模式进行优化
首先,先创建一个接口
package com.example.jdk8demo.lambda; public interface EmpolyerService<T> {
boolean filter(T t);
}
然后针对不同的需求,做不同的实现类
第一个实现类是针对查询年龄大于35的员工
package com.example.jdk8demo.lambda; public class EmpolyerImplByage implements EmpolyerService<Employer> {
@Override
public boolean filter(Employer employer) {
return employer.getAge() > ;
}
}
第二个实现类是针对查询公司大于4000的员工
package com.example.jdk8demo.lambda; public class EmpolyerImplBySalary implements EmpolyerService<Employer> {
@Override
public boolean filter(Employer employer) {
return employer.getSalary() > ;
}
}
然后就是使用策略模式进行查询,方法的入参是接口的实现类,然后根据实现类中对接口方法的不同实现进行不同的处理。
/**
* 使用策略模式查询员工信息
* @param empolyerService
* @return
*/
public List<Employer> getEmpolyerList(EmpolyerService<Employer> empolyerService){
List<Employer> employerList = new ArrayList<>();
for (Employer employer : list){
if(empolyerService.filter(employer)){
employerList.add(employer);
}
}
return employerList;
}
最后所有需求都统一调用新增的策略模式方法,具体的入参就是接口具体的实现类
/**
* 优化一:采用策略模式
*/
public void test5(){
List<Employer> employerList = getEmpolyerList(new EmpolyerImplByage());
for (Employer employer : employerList){
log.info(employer.toString());
}
log.info("=============================================");
employerList = getEmpolyerList(new EmpolyerImplBySalary());
for (Employer employer : employerList){
log.info(employer.toString());
}
}
这种优化也有不好的地方,就是一个需求就要创建一个实现类,随着需求的增加,实现类会越来越多,所以可以进一步进行优化
优化方案二:使用匿名内部类
由于采用策略模式,一个需求就需要创建一个实现类,导致文件增多,因此可以将策略模式改为使用匿名内部类,使用匿名内部类,仍然需要上述的过滤接口,但是无需再使用接口的实现类
/**
* 优化方式二:匿名内部类
*/
public void test6(){
List<Employer> employerList = getEmpolyerList(new EmpolyerService<Employer>() {
@Override
public boolean filter(Employer employer) {
return employer.getAge() > ;
}
});
for (Employer employer : employerList){
log.info(employer.toString());
}
log.info("=============================================");
employerList = getEmpolyerList(new EmpolyerService<Employer>() {
@Override
public boolean filter(Employer employer) {
return employer.getSalary() > ;
}
});
for (Employer employer : employerList){
log.info(employer.toString());
}
}
由此已经对应了本文刚开始的时候,匿名内部类中有用的代码实际就一行,但是缺需要写大量其他无用的代码,因此可以使用lambda进行优化。
优化方案三:使用lambda
/**
* 优化方式七:lambda表达式
*/
public void test7(){
LambdaTest lambdaTest = new LambdaTest();
List<Employer> employerList = lambdaTest.getEmpolyerList((e) -> e.getAge()>);
employerList.forEach(System.out::println);
log.info("=============================================");
employerList = lambdaTest.getEmpolyerList((e)->e.getSalary()>);
employerList.forEach(System.out::println);
}
可以发现,使用lambda表达式后,代码简单、简洁。到此处,为什么要使用lambda已经描述完毕,但是对于java8来说,还有更简洁的优化方式,就是Stream流。
优化方式四:Stream流
此种实现,不需要像前三种优化方式一样新建接口,这里直接使用流式过滤即可。
/**
* 使用StreamAPI查询员工信息
*/
public void test8(){
list.stream()//流式处理
.filter((e)->e.getSalary()>)//过滤出工资大于2000的员工
.filter((e)->e.getAge()>)//过滤出年龄大于30的员工
.limit()//只查询前两条
.forEach(System.out::println);//循环打印
}
JDK8--02:为什么要使用lambda的更多相关文章
- 02、Java的lambda表达式和JavaScript的箭头函数
前言 在JDK8和ES6的语言发展中,在Java的lambda表达式和JavaScript的箭头函数这两者有着千丝万缕的联系:本次试图通过这篇文章弄懂上面的两个"语法糖". 简介 ...
- Jdk8的学习之lambda
在JDK8中,引入了Lambda(读:了母达)表达式的概念,这是我最喜欢的特性,很多东西都变得简单了,一行代码可以搞定. 比如说排序 /** * 这是一个JDK8的lambda的排序应用 */ pub ...
- JDK8新特性之一Lambda
JDK8的新特性之一Lambda能将函数作为方法里面的参数使用. /** * JDK8新特性Lambda */ public class Test { public static void main( ...
- JDK15就要来了,你却还不知道JDK8的新特性!
微信搜「烟雨星空」,白嫖更多好文. 现在 Oracle 官方每隔半年就会出一个 JDK 新版本.按时间来算的话,这个月就要出 JDK15 了.然而,大部分公司还是在使用 JDK7 和 8 . 之前去我 ...
- JDK8.0新特性
连接转载地址:http://www.2cto.com/kf/201609/544044.html Eclipse: http://aiyiupload.oss-cn-beijing.aliyuncs. ...
- JDK8到JDK12各个版本的重要特性整理
JDK8新特性 1.Lambda表达式 2.函数式编程 3.接口可以添加默认方法和静态方法,也就是定义不需要实现类实现的方法 4.方法引用 5.重复注解,同一个注解可以使用多次 6.引入Optiona ...
- SpringCloudGateWay学习 之 从函数式编程到lambda
文章目录 前言: 函数式编程: 什么是函数式编程: 函数式编程的特点 lambda表达式: 核心: 函数接口: 方法引用: 类型推断: 变量引用: 级联表达式跟柯里化: 前言: 这一系列的文章主要是为 ...
- 看看 JDK 8 给我们带来什么(转)
世界正在缓慢而稳步的改变.这次改变给我们带来了一个新模样的JDK7,java社区也在一直期盼着在JDK8,也许是JDK9中出现一些其他的改进.JDK8的改进目标是填补JDK7实现中的一些空白——部分计 ...
- Django框架
一.首先,到底什么是框架? 想要回答这个问题,我们要慢慢来. ①首先从DRY原则开始说起 Don't Repeat Yourself,不要重复你的代码. DRY原则的重要性怎么提都不过分,很多人说编程 ...
- JAVA开发第一步——JDK 安装
JDK,Java Development Kit. And JRE ,Java Runtime Environment. jdk分64位和32位,可自行去Oracle官网下载 直接百度下载链接 Win ...
随机推荐
- Rocket - util - AsyncQueue
https://mp.weixin.qq.com/s/6McbqOKM4fu4J5vdpZvxKw 简单介绍异步队列(AsyncQueue)的实现. 0. 异步队列 异步队列的两端分 ...
- Redis 入门到分布式 (一)Redis初识
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.Redis特性目录 Redis的特性: 速度快 持久化 多种数据结构 支持多种编辑语言 功能丰富 简 ...
- ASP.NET中LINQ的基本用法
此Demo只是一个极其简单的LINQ查询Demo 一个类 using System; using System.Collections.Generic; using System.Linq; usin ...
- Java实现 LeetCode 629 K个逆序对数组(动态规划+数学)
629. K个逆序对数组 给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数. 逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < ...
- Java实现 LeetCode 395 至少有K个重复字符的最长子串
395. 至少有K个重复字符的最长子串 找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k .输出 T 的长度. 示例 1: 输入: s = " ...
- ReentrantLock原理分析
一 UML类图 通过类图ReentrantLock是同步锁,同一时间只能有一个线程获取到锁,其他获取该锁的线程会被阻塞而被放入AQS阻塞队列中.ReentrantLock类继承Lock接口:内部抽象类 ...
- javaScript的执行机制-同步任务-异步任务-微任务-宏任务
一.概念理解 1.关于javascript javascript是一门单线程语言,在最新的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变.所以一切javascr ...
- 实验四 Linux系统C语言开发环境学习
项目 内容 这个作业属于哪个课程 Linux系统与应用 这个作业的要求在哪里 作业要求链接 学号-姓名 17041428-朱槐健 作业学习目标 1.Linux系统下C语言开发环境搭建 2.学习Linu ...
- spring-framework 源码的下载与构建
整体流程: 本地环境准备 找到源码地址并拉取到本地 根据IDE工具查看源码中提供的不同的安装说明并具体操作 构建会出现的的错误及解决 一.本地环境准备 spring-framework 源码使用gra ...
- Html/css 水平布局居中
如何设置水平居中显示? 一般的方法是设置宽高,然后以margin去控制,比如:DIV居中的经典方法 本章介绍需要宽度自适应时如何水平居中,以及居中失效的几个点 水平自适应居中 比如设置一个列表水平居中 ...