Lambda表达式介绍

Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。通过Lambda表达式,可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数;

体验Lambda表达式

我们通过一个小例子来体验下Lambda表达式;

我们定义一个计算接口 只有一个方法add;

public class Program {

    public static void main(String[] args) {
Cal c1=new Cal() {
@Override
public int add(int a, int b) {
return a+b;
}
};
int c=c1.add(,);
System.out.println(c);
}
} interface Cal{
int add(int a,int b);
}

这个是我们以前的实现,匿名内部类,然后调用执行;

我们现在用Lambda表达式改写下:

public class Program {

    public static void main(String[] args) {
Cal c1=(int a,int b) ->{return a+b;};
int c=c1.add(,);
System.out.println(c);
} int add(int a,int b){
return a+b;
}
} interface Cal{
int add(int a,int b);
}

匿名内部类,直接改成了:

Cal c1=(int a,int b) ->{return a+b;};

简洁多了;

是不是感觉Lambda表达式挺强大,

接下来我们来看看Lambda表达式的语法吧;

Lambda表达式语法

我们看下这个Lambda表达式:

(int a,int b) ->{return a+b;};

这个本质是一个函数;

一般的函数类似如下:

int add(int a,int b){
return a+b;
}

有返回值,方法名,参数列表,方法体 

Lambda表达式函数的话,只有参数列表,和方法体;

( 参数列表 ) -> { 方法体 }

说明:

( ) :用来描述参数列表;

{ } : 用来描述方法体;

->  :Lambda运算符,可以叫做箭头符号,或者goes to

Lambda表达式语法细讲

我们搞一个案例,接口方法参数,无参,单个参数,两个参数,有返回值,没有返回值,这六种情况都罗列下:

interface If1{

    /**
* 无参数无返回值
*/
void test();
} interface If2{ /**
* 单个参数无返回值
* @param a
*/
void test(int a);
} interface If3{ /**
* 两个参数无返回值
* @param a
* @param b
*/
void test(int a,int b);
} interface If4{ /**
* 无参数有返回值
* @return
*/
int test();
} interface If5{ /**
* 单个参数有返回值
* @param a
* @return
*/
int test(int a);
} interface If6{ /**
* 多个参数有返回值
* @param a
* @param b
* @return
*/
int test(int a,int b);
}

我们用Lambda表达式实现:

// 无参数无返回值
If1 if1=()->{
System.out.println("无参数无返回值");
};
if1.test(); // 单个参数无返回值
If2 if2=(int a)->{
System.out.println("单个参数无返回值 a="+a);
};
if2.test(); // 两个参数无返回值
If3 if3=(int a,int b)->{
System.out.println("两个参数无返回值 a+b="+(a+b));
};
if3.test(,); // 无参数有返回值
If4 if4=()->{
System.out.print("无参数有返回值 ");
return ;
};
System.out.println(if4.test()); // 单个参数有返回值
If5 if5=(int a)->{
System.out.print("单个参数有返回值 ");
return a;
};
System.out.println(if5.test()); // 多个参数有返回值
If6 if6=(int a,int b)->{
System.out.print("多个参数有返回值 ");
return a+b;
};
System.out.println(if6.test(,));

运行输出:

无参数无返回值
单个参数无返回值 a=
两个参数无返回值 a+b=
无参数有返回值
单个参数有返回值
多个参数有返回值

Lambda表达式精简语法

那件语法注意点:

  • 参数类型可以省略
  • 假如只有一个参数,()括号可以省略
  • 如果方法体只有一条语句,{}大括号可以省略
  • 如果方法体中唯一的语句是return返回语句,那省略大括号的同事return也要省略

改写实例:

/**
* @author java1234_小锋
* @site www.java1234.com
* @company Java知识分享网
* @create 2020-08-12 16:43
*/
public class Program2 { public static void main(String[] args) {
// 1,参数类型可以省略
// 2,假如只有一个参数,()括号可以省略
// 3,如果方法体只有一条语句,{}大括号可以省略
// 4,如果方法体中唯一的语句是return返回语句,那省略大括号的同事return也要省略 // 无参数无返回值
If1 if1=()->System.out.println("无参数无返回值");
if1.test(); // 单个参数无返回值
If2 if2=a->System.out.println("单个参数无返回值 a="+a);
if2.test(); // 两个参数无返回值
If3 if3=(a,b)->{
System.out.println("两个参数无返回值 a+b="+(a+b));
};
if3.test(,); // 无参数有返回值
If4 if4=()->;
System.out.println(if4.test()); // 单个参数有返回值
If5 if5=a->{
System.out.print("单个参数有返回值 ");
return a;
};
System.out.println(if5.test()); // 多个参数有返回值 参数类型可以省略
If6 if6=(a,b)->a+b;
System.out.println(if6.test(,)); } }

方法引用

有时候多个lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护;

这时候可以用方法引用实现:

语法是:对象::方法

假如是static方法,可以直接 类名::方法

实例如下:

public class Program2 {

    public static void main(String[] args) {
// 方法引用
// 语法:
// static方法 类名::方法名
// 普通方法 对象名::方法名
Program2 program2=new Program2();
If5 if5=program2::test;
If5 if52=Program2::test2;
System.out.println(if5.test());
System.out.println(if52.test()); } public int test(int a){
return a-;
} public static int test2(int a){
return a-;
} }

构造方法引用

如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,

那么就可以使用构造方法引用;

语法:类名::new

实例:

先定义一个Dog实体,实现无参和有参构造方法;

public class Dog {

    private String name;

    private int age;

    public Dog() {
System.out.println("无参构造方法");
} public Dog(String name, int age) {
System.out.println("有参构造方法");
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

在定义两个接口:

interface DogService{
Dog getDog(); } interface DogService2{
Dog getDog(String name,int age);
}

测试:

public class Program3 {

    public static void main(String[] args) {

        // 普通方式
DogService dogService=()->{
return new Dog();
};
dogService.getDog(); // 简化方式
DogService dogService2=()->new Dog();
dogService2.getDog(); // 构造方法引用
DogService dogService3=Dog::new;
dogService3.getDog(); // 构造方法引用 有参
DogService2 dogService21=Dog::new;
dogService21.getDog("小米",);
}
}

执行结果:

无参构造方法
无参构造方法
无参构造方法
有参构造方法

综合实例

下面我们通过一个lambda操作集合的综合实例,来深入体验下Lambda表达式用法;

public class Program4 {

    public static void main(String[] args) {
List<Dog> list=new ArrayList<>();
list.add(new Dog("aa",));
list.add(new Dog("bb",));
list.add(new Dog("cc",));
list.add(new Dog("dd",));
list.add(new Dog("ee",));
// 排序
System.out.println("lambda集合排序");
list.sort((o1,o2)->o1.getAge()-o2.getAge());
System.out.println(list); // 遍历集合
System.out.println("lambda遍历集合");
list.forEach(System.out::println);
}
}

运行输出:

lambda集合排序
[Dog{name='aa', age=}, Dog{name='dd', age=}, Dog{name='cc', age=}, Dog{name='bb', age=}, Dog{name='ee', age=}]
lambda遍历集合
Dog{name='aa', age=}
Dog{name='dd', age=}
Dog{name='cc', age=}
Dog{name='bb', age=}
Dog{name='ee', age=}

我们来分析下集合的sort方法,

sort方法里有一个Comparator接口,再点进去看下:

我们通过lambda就可以轻松实现排序:

(o1,o2)->o1.getAge()-o2.getAge()

再看下集合的forEach方法,点进去:

有个消费者Consumer接口,再点进去:

接口里有个接口参数的accept的方法;

所以我们直接方法引用 直接输出每次的遍历值即可;

System.out::println

@FunctionalInterface注解

前面我们会发现Consumer接口,Comparator接口都有

@FunctionalInterface注解;

这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces

特点

  • 接口有且仅有一个抽象方法

  • 允许定义静态方法

  • 允许定义默认方法

  • 允许java.lang.Object中的public方法

该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

实例

// 正确的函数式接口
@FunctionalInterface
public interface TestInterface { // 抽象方法
public void sub(); // java.lang.Object中的public方法
public boolean equals(Object var1); // 默认方法
public default void defaultMethod(){ } // 静态方法
public static void staticMethod(){ }
} // 错误的函数式接口(有多个抽象方法)
@FunctionalInterface
public interface TestInterface2 { void add(); void sub();
}

系统内置函数式接口

Java8的推出,是以Lambda重要特性,一起推出的,其中系统内置了一系列函数式接口;

再jdk的java.util.function包下,有一系列的内置函数式接口:

比如常用的Consumer,Comparator,Predicate,Supplier等;

Lambda表达式视频教程

感谢各位兄弟姐妹关注,锋哥为了大伙能更深刻的掌握Lambda的原理和应用,专门录制了一期视频教程。主要以IDEA开发工具,来讲解lambda表达式,希望小伙伴们快速的掌握。

纸上得来终觉浅,绝知此事要躬行。

需要多实战,多思考

B站视频教程在线地址:
https://www.bilibili.com/video/bv1ci4y1g7qD

------------------------------------------------------------------------------------------------------------------------------

作者:java1234_小锋

出处:https://www.cnblogs.com/java688/p/13511720.html

版权:本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。

------------------------------------------------------------------------------------------------------------------------------

一文搞懂Java8 Lambda表达式(附带视频教程)的更多相关文章

  1. Java8 Lambda表达式详解手册及实例

    先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...

  2. java8 Lambda表达式的新手上车指南(1)

    背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...

  3. 一文搞懂RAM、ROM、SDRAM、DRAM、DDR、flash等存储介质

    一文搞懂RAM.ROM.SDRAM.DRAM.DDR.flash等存储介质 存储介质基本分类:ROM和RAM RAM:随机访问存储器(Random Access Memory),易失性.是与CPU直接 ...

  4. java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口

    背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...

  5. 基础篇|一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  6. 一文搞懂 Prometheus 的直方图

    原文链接:一文搞懂 Prometheus 的直方图 Prometheus 中提供了四种指标类型(参考:Prometheus 的指标类型),其中直方图(Histogram)和摘要(Summary)是最复 ...

  7. Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

    本文原作者: Wizey,作者博客:http://wenshixin.gitee.io,即时通讯网收录时有改动,感谢原作者的无私分享. 1.引言 典型的Web端即时通讯技术应用场景,主要有以下两种形式 ...

  8. 一文搞懂vim复制粘贴

    转载自本人独立博客https://liushiming.cn/2020/01/18/copy-and-paste-in-vim/ 概述 复制粘贴是文本编辑最常用的功能,但是在vim中复制粘贴还是有点麻 ...

  9. 三文搞懂学会Docker容器技术(中)

    接着上面一篇:三文搞懂学会Docker容器技术(上) 6,Docker容器 6.1 创建并启动容器 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] --na ...

随机推荐

  1. 高效C++:定制new和delete

    内存的申请和释放,C++从语言级别提供了new和delete关键字,因此需要了解和熟悉其中的过程. 了解new-handler的行为 set_new_handler可以指定一个函数,当申请内存失败时调 ...

  2. Django Models随机获取指定数量数据方法

    方法一:新增models的Manager方法 下面就直接发代码了 class RandomManager(models.Manager): def get_queryset(self): return ...

  3. 面试题四十三:在1~n整数中1出现的次数

    方法一:直观来看,遍历1到n,每个数去做%10的循环判断 int Number1_B_1toN( int n){ int sum=0; for(int i=1;i<=n;i++){ int k= ...

  4. Spring Boot 太狠了,一次性发布了 3 个版本!

    Spring Boot 太狠了,北京时间 2020/07/25 今天一次性发布了三个主要版本,三条版本线同时更新: Spring Boot 2.3.2 Spring Boot 2.2.9 Spring ...

  5. Python操作adb命令脚本

    一.脚本代码(有错误,抓紧改进中) import os import datetime date1=datetime.datetime.now().strftime('%Y%m%d') date2=d ...

  6. 为PhpStorm添加Laravel 代码智能提示功能

    php artisan clear-compiled //清除bootstrap/compiled.php php artisan ide-helper:generate //为 Facades 生成 ...

  7. Python2.7 PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed 问题解决

    # 报错信息 PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.insta ...

  8. PHP 超级全局变量讲解

    PHP 超级全局变量 超级全局变量在PHP 4.1.0之后被启用, 是PHP系统中自带的变量,在一个脚本的全部作用域中都可用. PHP 超级全局变量 PHP中预定义了几个超级全局变量(superglo ...

  9. Python os.remove() 方法

    概述 os.remove() 方法用于删除指定路径的文件.如果指定的路径是一个目录,将抛出OSError.高佣联盟 www.cgewang.com 在Unix, Windows中有效 语法 remov ...

  10. 牛客练习赛64 红色的樱花 exgcd 贪心

    LINK:The red sakura 暴怒狂樱 血染京都. 这题质量不咋地 这题也没啥营养. 不过还是存在值得学习的地方的. 一个trick n行 m列 第一行与第n行相连 第1列和第m列相连的时候 ...