一、Lambda表达式的介绍

  • Lambda表达式是 Java8 中最重要的新功能之一。使用 Lambda 表达

    式可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看

    起来更简洁易懂。Lambda表达式同时还提升了对集合、框架的迭代、

    遍历、过滤数据的操作。

  • lambda表达式可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂

  • lambda表达式同时还提升了对集合、框架的迭代、遍历、过滤数据的操作

  • lambda可以极大的减少代码冗余,同时代码的可读性要好过冗长的内部类,匿名类

例如以前我们使用匿名内部类来实现代码:

        Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("running1 .....");
}
};
runnable.run();

使用lambda表达式实现更简洁的代码:

        Runnable runnable3 = ()-> System.out.println("running2....");
runnable3.run();

lambda表达式语法:

LambdaParameters -> LambdaBody



args -> expr或者(object ... args)-> {函数式接口抽象方法实现逻辑}

​ 1、()参数的个数,根据函数式接口里面抽象的参数个数来决定,当参数只有一个的时候,()可以省略

​ 2、当expr逻辑非常简单的时候,{}和return可以省略

案例说明:

    public static void main(String[] args) throws Exception {
Callable<String> c1 = new Callable() {
@Override
public String call() throws Exception {
return "muxiaonong";
}
};
System.out.println(c1.call()); Callable<String> c2 = ()->{return "muxiaonong2";};
System.out.println(c2.call()); //逻辑很简单的时候省略 {} 和 return
Callable<String> c3 = ()->"muxiaonong3";
System.out.println(c3.call());
}

二、Lambda表达式的特点

  • 函数式编程
  • 参数类型自动推断
  • 代码量少,简洁

三、Lambda表达式案例

实现方式列表:

​	    ()->{}
​ ()->{System.out.println(1);}
​ ()->System.out.println(1)
​ ()->{return 100;}
​ ()->100
​ ()->null
​ (int x)->{return x+1;}
​ (int x)->x+1
​ (x)->x+1
​ x->x+1

案例1:线程实现方式:

    public static void main(String[] args) {
//匿名内部类方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("runing1..........");
}
}); //Lambda表达式方式
new Thread(() -> {System.out.println("runing2.....");}).start();
}

案例2:集合遍历实现方式

    public static void main(String[] args) {
List<String> list = Arrays.asList("java","python","scala","javascript"); //普通匿名内部类方式
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}); //Lambda方式
Collections.sort(list,(a,b) -> a.length() - b.length());
list.forEach(System.out::println);
}

四、Lambda表达式的应用场景

重要的事情说三遍:任何有函数式接口的地方 * 3

什么是函数式接口: 只有一个抽象方法(Object类中的方法除外)的接口是函数式接口

五、Lambda表达式实际应用

5.1 无参实体类模拟

模拟数据库连接层:

@FunctionalInterface
public interface StudentDao {
void insert(Student student);
}

实体类

/** @Author mxn
* @Description 学生实体类
* @Date 10:19 2020/11/7
* @Param
* @return
**/
public class Student {
}
 public static void main(String[] args) {
StudentDao sd1 = new StudentDao() {
@Override
public void insert(Student student) {
System.out.println("插入学生1");
}
}; StudentDao sd2 = (student)->{
System.out.println("student: "+student);
}; StudentDao sd3 = (Student student)-> System.out.println("student3:"+student); sd1.insert(new Student()); //输出 插入学生1
sd2.insert(new Student());// 输出
sd3.insert(new Student());// 输出
}

5.2 有参实体类模拟

实体类

/** @Author mxn
* @Description
* @Date 10:26 2020/11/7
* @Param
* @return
**/
public class Teacher {
}

接口模拟层

@FunctionalInterface
public interface TeacherDao {
int get(Teacher teacher);
}

实现层

 public static void main(String[] args) {
TeacherDao td1 = new TeacherDao() {
@Override
public int get(Teacher teacher) {
return 1;
}
};
TeacherDao td2 = (teacher)->{return 2;};
TeacherDao td3 = (Teacher teacher)->{return 3;};
TeacherDao td4 = (teacher)->4;
TeacherDao td5 = (Teacher teacher)->5; System.out.println(td1.get(new Teacher()));//输出 1
System.out.println(td2.get(new Teacher()));//输出 2
System.out.println(td3.get(new Teacher()));//输出 3
System.out.println(td4.get(new Teacher()));//输出 4
System.out.println(td5.get(new Teacher()));//输出 5
}

六、函数式接口

Supplier:代表一个输出

Consumer:代表一个输入

BiConsumer:代表两个输入

Function:代表一个输入,一个输出(一般输入和输出是不同类型的)

UnaryOperator:代表一个输入,一个输出(输入和输出是相同类型的)

BiFunction:代表两个输入,一个输出(一般输入和输出是不同类型的)

BinaryOperator:代表两个输入,一个输出(输入和输出是相同类型的)

在Java中提供了一系列的函数式接口,用来接受后续传入的逻辑,但是对输入和输出有要求

6.1 Supplier:代表一个输出

 		Supplier<String> s1 = ()->{return "muxiaonong";};
Supplier<String> s2 = ()->"muxiaonong2";
System.out.println(s1.get());//输出 muxiaonong
System.out.println(s2.get());//输出 muxiaonong2

6.2 Consumer:代表一个输入

	    Consumer<String> c11 = (str) -> System.out.println(str);
c11.accept("beijing");//输出 beijing

6.3 BiConsumer:代表两个输入

		BiFunction<String,String,Integer> bf = (a,b)->a.length()+b.length();
System.out.println(bf.apply("大吉大利", "今晚吃鸡"));//输出一个字符串长度 8

6.4 Function:代表一个输入,一个输出

//  Function<String,Integer>  用来接收后面的函数的实现,规定必须有一个输入(String)有一个输出(Integer)
Function<String,Integer> f1 = (str)->{return str.length();};
System.out.println(f1.apply("abcdefg"));//输出长度 7

七、方法的引用

  • 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用

7.1 方法引用的分类

类型 语法 对应的lambda表达式
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) -> 类名.instMethod(args)
构造方法引用 类名::new (args) -> new 类名(args)

7.2 静态方法引用

  • 静态方法引用: 如果函数式接口的实现恰好可以通过 调用一个静态方法 来实现,那么就可以使用静态方法引用

/**
* @program: lambda
* @ClassName Test2
* @description:
* @author: muxiaonong
* @create: 2020-10-28 22:15
* @Version 1.0
**/
public class Test2 {
//无参静态方法
static String put(){
System.out.println("put.....");
return "put";
} //有参静态方法
public static void getSize(int size){
System.out.println(size);
} //有参 有返回值静态方法
public static String toUpperCase(String str){
return str.toUpperCase();
} //两个入参,一个返回值静态方法
public static Integer getLength(String str,String str2){
return str.length()+str2.length();
} public static void main(String[] args) {
//无参静态方法-普通调用
System.out.println(put());//输出put
//无参静态方法-原生调用
Supplier<String> s1 = ()-> Test2.put();
System.out.println(s1.get());//输出put
//无参静态方法-静态方法引用
Supplier<String> s2 = Test2::put;
System.out.println(s2.get());//输出put
//无参静态方法-内部类调用
Supplier<String> s3 = Fun::hehe;
System.out.println(s3.get()); //输出hehe // 有参静态方法-静态方法引用
Consumer<Integer> c1 = Test2::getSize;
Consumer<Integer> c2 = (size)-> Test2.getSize(size);
c1.accept(123);
c2.accept(111); //有参有返回值静态方法
Function<String,String> f1 = (str)->str.toUpperCase();
Function<String,String> f2 = (str)-> Test2.toUpperCase(str);
Function<String,String> f3 = Test2::toUpperCase;
Function<String,String> f4 = Test2::toUpperCase; System.out.println(f1.apply("abc"));//输出 ABC
System.out.println(f2.apply("abc"));//输出 ABC
System.out.println(f3.apply("abc"));//输出 ABC
System.out.println(f4.apply("abc"));//输出 ABC // 两个参数 一个返回值 函数式接口
BiFunction<String,String,Integer> bf = (a, b)->a.length()+b.length();
BiFunction<String,String,Integer> bf2 = Test2::getLength;
System.out.println(bf2.apply("abc", "def"));//输出 6
System.out.println(bf.apply("abc", "def"));//输出 6 } //内部类
class Fun {
public static String hehe(){
return "hehe";
} public static String toUpperCase(String str){
return str.toUpperCase();
} } }

7.3 实例方法引用

  • 实例方法引用: 如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
public class Test3 {
//实例无参方法
public String put(){
return "put...";
} //实例有参方法
public void getSize(int size){
System.out.println("size:"+size);
} //实例有参有返回值方法
public String toUpperCase(String str){
return str.toUpperCase();
}
public static void main(String[] args) {
//实例无参方法返回-普通调用
System.out.println(new Test3().put());//输出 put...
Supplier<String> s1 = ()->new Test3().put();
Supplier<String> s2 = ()->{return new Test3().put();};
Supplier<String> s3 = new Test3()::put;
System.out.println(s1.get());//输出 put...
System.out.println(s2.get());//输出 put...
System.out.println(s3.get());//输出 put... //唯一的创建一个test3对象
Test3 test = new Test3(); Consumer<Integer> c1 = (size)->new Test3().getSize(size);
Consumer<Integer> c2 = new Test3()::getSize;
Consumer<Integer> c3 = test::getSize; c1.accept(123);//输出 size:123
c2.accept(123);//输出 size:123
c3.accept(123);//输出 size:123 Function<String,String> f1 = (str)->str.toUpperCase();
Function<String,String> f2 = (str)->test.toUpperCase(str);
Function<String,String> f3 = new Test3()::toUpperCase;
Function<String,String> f4 = test::toUpperCase;
System.out.println(f1.apply("abc"));//输出 ABC
System.out.println(f2.apply("abc"));//输出 ABC
System.out.println(f3.apply("abc"));//输出 ABC
System.out.println(f4.apply("abc"));//输出 ABC
}
}

7.4 对象方法引用

  • 对象方法引用: 抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
/** @Author mxn
* @Description //TODO 对象方法引用
* @Date 14:26 2020/11/7
* @Param
* @return
**/
public class Test4 {
public static void main(String[] args) {
Consumer<Too> c1 = (too)->new Too().foo();
c1.accept(new Too());//输出 foo Consumer<Too> c2 = (Too too) ->new Too2().foo();
c2.accept(new Too());//输出 foo---too2 Consumer<Too> c3 = Too::foo;
c3.accept(new Too());//输出 foo BiConsumer<Too2,String> bc = (too2,str)->new Too2().show(str);
BiConsumer<Too2,String> bc2 = Too2::show;
bc.accept(new Too2(),"abc");
bc2.accept(new Too2(),"def"); BiFunction<Exec,String,Integer> bf1 = (e,s)->new Exec().test(s);
bf1.apply(new Exec(),"abc");
BiFunction<Exec,String,Integer> bf2 = Exec::test;
bf2.apply(new Exec(),"def");
}
} class Exec{
public int test(String name){
return 1;
} } class Too{
public Integer fun(String s){
return 1;
}
public void foo(){
System.out.println("foo");
}
}
class Too2{
public Integer fun(String s){
return 1;
}
public void foo(){
System.out.println("foo---too2");
} public void show(String str){
System.out.println("show ---too2"+str);
}
}

7.5 构造方法引用

  • 构造方法引用: 如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
/** @Author mxn
* @Description //TODO 构造方法引用
* @Date 14:27 2020/11/7
* @Param
* @return
**/
public class Test5 {
public static void main(String[] args) {
Supplier<Person> s1 = ()->new Person();
s1.get();//输出 调用无参的构造方法
Supplier<Person> s2 = Person::new;
s2.get();//输出 调用无参的构造方法 Supplier<List> s3 = ArrayList::new;
Supplier<Set> s4 = HashSet::new;
Supplier<Thread> s5 = Thread::new;
Supplier<String> s6 = String::new; Consumer<Integer> c1 = (age)->new Account(age);
Consumer<Integer> c2 = Account::new;
c1.accept(123);// 输出 age 参数构造123
c2.accept(456);//输出 age 参数构造456 Function<String,Account> f1 = (str)->new Account(str);
Function<String,Account> f2 = Account::new;
f1.apply("abc");//输出 str 参数构造abc
f2.apply("def");//输出 str 参数构造def }
} class Account{
public Account(){
System.out.println("调用无参构造方法");
} public Account(int age){
System.out.println("age 参数构造" +age);
} public Account(String str){
System.out.println("str 参数构造" +str);
}
} class Person{
public Person(){
System.out.println("调用无参的构造方法");
}
}

八、小结

  • JAVA 8 引入 Lambda表达式是接收了函数式编程语言的思想,和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
  • lambda表达式可以使代码看起来简洁,但一定程度上增加了代码的可读性以及调试的复杂性,所以在使用时应尽量是团队都熟悉使用,要么干脆就别用,不然维护起来是件较痛苦的事,今天的小知识就到这里了,有问题的小伙伴可以在下方进行留言,大家加油!

JDK新特性-Lambda表达式的神操作的更多相关文章

  1. 乐字节-Java8新特性-Lambda表达式

    上一篇文章我们了解了Java8新特性-接口默认方法,接下来我们聊一聊Java8新特性之Lambda表达式. Lambda表达式(也称为闭包),它允许我们将函数当成参数传递给某个方法,或者把代码本身当作 ...

  2. Java8新特性-Lambda表达式是什么?

    目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...

  3. Java 8 新特性 - Lambda表达式

    Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...

  4. C#10新特性-lambda 表达式和方法组的改进

    C# 10 中对Lambda的语法和类型进行了多项改进: 1. Lambda自然类型 Lambda 表达式现在有时具有"自然"类型. 这意味着编译器通常可以推断出 lambda 表 ...

  5. 大数据之路week06--day03(jdk8新特性 Lambda表达式)

    为什么使用Lambda表达式?(做为初学者接触这个新的语法,会很懵逼,说道理,我在接触到这一块的时候,语法规则我看到了也很懵逼,因为这个和逻辑的关系不是很大,但就是作为一种新的语法出现,一时间很难接受 ...

  6. Java8新特性: lambda 表达式介绍

    一.lambda 表达式介绍 lambda 表达式是 Java 8 的一个新特性,可以取代大部分的匿名内部类,简化了匿名委托的使用,让你让代码更加简洁,优雅. 比较官方的定义是这样的: lambda ...

  7. JDK8的新特性——Lambda表达式

    JDK8已经发布快4年的时间了,现在来谈它的新特性显得略微的有点“不合时宜”.尽管JDK8已不再“新”,但它的重要特性之一——Lambda表达式依然是不被大部分开发者所熟练运用,甚至不被开发者所熟知. ...

  8. java8新特性——Lambda表达式

    上文中简单介绍了一下java8得一些新特性,与优点,也是为本次学习java8新特性制定一个学习的方向,后面几篇会根据上文中得新特性一一展开学习.本文就从java8新特性中比较重要的Lambda表达式开 ...

  9. jdk8的新特性 Lambda表达式

    很多同学一开始接触Java8可能对Java8 Lambda表达式有点陌生. //这是一个普通的集合 List<Employee> list = em.selectEmployeeByLog ...

随机推荐

  1. 079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象

    079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象 本文知识点:实例化对象 说明:因为时间紧张,本人写博客过程中只是对知 ...

  2. OpenCV计算机视觉学习(2)——图像算术运算 & 掩膜mask操作(数值计算,图像融合,边界填充)

    在OpenCV中我们经常会遇到一个名字:Mask(掩膜).很多函数都使用到它,那么这个Mask到底是什么呢,下面我们从图像基本运算开始,一步一步学习掩膜. 1,图像算术运算 图像的算术运算有很多种,比 ...

  3. TTL和CMOS电平

    参考: 1.https://baike.baidu.com/item/TTL%E7%94%B5%E5%B9%B3/5904345 2.https://baike.baidu.com/item/CMOS ...

  4. P5911 [POI2004]PRZ (状态压缩dp+枚举子集)

    题目背景 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 题目描述 桥已经很旧了, 所以它不能承受太重的东西.任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时 ...

  5. MLHPC 2018 | Aluminum: An Asynchronous, GPU-Aware Communication Library Optimized for Large-Scale Training of Deep Neural Networks on HPC Systems

    这篇文章主要介绍了一个名为Aluminum通信库,在这个库中主要针对Allreduce做了一些关于计算通信重叠以及针对延迟的优化,以加速分布式深度学习训练过程. 分布式训练的通信需求 通信何时发生 一 ...

  6. 洛谷P1450 [HAOI2008]硬币购物 背包+容斥

    无限背包+容斥? 观察数据范围,可重背包无法通过,假设没有数量限制,利用用无限背包 进行预处理,因为实际硬币数有限,考虑减掉多加的部分 如何减?利用容斥原理,减掉不符合第一枚硬币数的,第二枚,依次类推 ...

  7. Informatica报错“表或视图不存在”的某种原因

    软件版本:9.6.1 背景:测试将OLTP数据库的用户信息表(CUST_INFO)抽取到DW库(DW_CUST_INFO) 问题:工作流启动后,报错RR_4035,并告知表或视图不存在 分析:在导入源 ...

  8. linux(centos8):用tr替换或删除字符

    一,tr命令的用途 tr命令可以替换或删除文件中的字符 它从标准输入设备读取数据, 处理完成将结果输出到标准输出设备 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnbl ...

  9. mac 安装appium

    mocOS 10.15.5 开启方式:设置->默认编辑器->Markdown编辑器

  10. javascript 数字 字母 互转

    var alphabet= String.fromCharCode(64 + parseInt(填写数字); 单个字符转数字: 'a'.charCodeAt(0) 结果: 97 数字转字母: Stri ...