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 ...
随机推荐
- .net remoting(一)
一.远程对象 ①RemoteHello.csproj 类库项目,程序集名称 RemoteHello ,默认命名空间 Wrox.ProCSharp.Remoting: ②派生自System.Marssh ...
- SpringMVC(二)返回值设置、数据在域中的保存与SpringMVC案例
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.返回值的设置 1.返回 String [1]返回 String 默认情况 @RequestMappi ...
- golang内存逃逸
golang程序变量会携带油一组校验数据,用来证明它的整个生命周期是否在运行时完全可知.如果变量通过了这些校验,它就可以在栈上分配.否则就说它逃逸了,必须在堆上分配 能引起变量逃逸到堆上的典型 ...
- Java实现 LeetCode 706 设计哈希映射(数组+链表)
706. 设计哈希映射 不使用任何内建的哈希表库设计一个哈希映射 具体地说,你的设计应该包含以下的功能 put(key, value):向哈希映射中插入(键,值)的数值对.如果键对应的值已经存在,更新 ...
- Java实现蓝桥杯历届真题国王的遗产
国王的遗产 题目描述 X国是个小国.国王K有6个儿子.在临终前,K国王立下遗嘱:国王的一批牛作为遗产要分给他的6个儿子. 其中,大儿子分1/4,二儿子1/5,三儿子1/6,- 直到小儿子分1/9. 牛 ...
- Java实现子序列问题
一个串的子串是指该串的一个连续的局部.如果不要求连续,则可称为它的子序列. 比如对串: "abcdefg" 而言,"ab","abd",&q ...
- Java实现 洛谷 P1010 幂次方
输入输出样例 输入 #1 1315 输出 #1 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0) import java.util.Scanner; pu ...
- java实现字符串比较
标题:字符串比较 我们需要一个新的字符串比较函数compare(s1, s2). 对这个函数要求是: 1. 它返回一个整数,表示比较的结果. 2. 结果为正值,则前一个串大,为负值,后一个串大,否则, ...
- Linux 源码包安装过程
安装准备 安装gcc编译器 下载源码包 源代码保存位置:/usr/local/src/ 软件安装位置:/usr/local/ 解压缩下载的源码包 进入解压缩目录 软件配置与检查:./configure ...
- CSS 简介/特点/优势/给特定浏览器提供不同样
1.CSS简介 CSS全称Cascading Style Sheet,可译为“层叠样式表”或“级联样式表”,通常称为CSS样式或者样式表.CSS是一些纯文本内容,文件格式为.css. 2.CSS特点 ...