Java8-新特性及Lambda表达式

news/2024/4/30 2:28:37/文章来源:https://blog.csdn.net/qq_57404736/article/details/128039932

1、Java8新特性内容概述

1.1、简介

Java 8(又称为jdk1.8)是Java语言开发的一个主要版本

Java 8是oracle公司于2014年3月发布,可以看成是自Java 5以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性

1.2、新特性思维导图总结

在这里插入图片描述

1.3、新特性好处

  • 速度更快
  • 代码更少==(增加了新的语法:lambda表达式)==
  • 强大的StreamAPI
  • 最大化减少空指针异常:Optional
  • Nashorn引擎,允许在JVM上运行JS应用

2、Lambda表达式概述

2.1、为什么使用

lambda是一个匿名函数,我们可以把lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提示。

2.2、语法

Lamdba表达式:在Java8语言中引入的一种新的语法元素和操作符。这个操作符为->,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

  • 左侧:指定了Lambda表达式需要的参数列表
  • 右侧:指定了Lambda体,是抽象方法的实现逻辑,也即Lambda表达式要执行的功能

举例:

(o1,o2) -> Integer.compare(o1,o2)

格式:

  • ->:lambda操作符 或 箭头操作符
  • 左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)
  • 右边:lambda体(其实就是重写的抽象方法的方法体)

3、lambda表达式快速使用

大致分为6种情况讲解

  • 无参无返回值

    Runnable run = () -> {System.out.println(111);
    };
    
  • 需要一个参数,但没有返回值

    Consumer<String> con = (String x) -> {System.out.println(x);
    };
    
  • 数据类型可以省略,因为可由编译器推断出来,称为类型推断

    Consumer<String> con = (x) -> {System.out.println(x);
    };
    
  • 若只需要一个参数时,参数的小括号可以省略

    Consumer<String> con = str -> {System.out.println(str);
    };
    
  • 若需要两个以上的参数,多条执行语句,并且可以有返回值

    Comparator<Integer> con = (x,y) -> {System.out.println(x);System.out.println(y);return Integer.compare(x,y);
    };
    
  • 当Lambda体只有一条语句时,return与大括号若有,都可以省略

    Comparator<Integer> con = (x,y) -> Integer.compare(x,y);
    

无参无返回值

因为Runnable接口里的唯一接口方法run()方法就是无参无返回值的方法,所以我们可以使用Lambda表示

public static void main(String[] args){Runnable runn = () -> {System.out.println("hello world!");};runn.run(); //hello world!
}

需要一个参数,但没有返回值

Consumer接口里的唯一接口方法accept就是接收一个参数,无返回值的方法,所以可以使用Lambda表示

public static void main(String[] args){Consumer<String> con = (String s) ->{System.out.println(s);};con.accept("hello world!"); // hello world!
}

数据类型可以省略

//Java可以类型推断,前面定义泛型,后面参数就不可能是其他类型了,所以可以省略
Consumer<String> con = (s) ->{System.out.println(s);
};
con.accept("hello world!"); // hello world!

若只需要一个参数时,参数的小括号可以省略

// 因为我们只有一个参数 s,所以小括号也可以省略,只有在参数个数等于1的时候,才能省略,小于或者大于都不能省略!!!
Consumer con = s ->{System.out.println(s);
};
con.accept("hello world!"); // hello world!

若需要两个以上的参数,多条执行语句,并且可以有返回值

public static void main(String[] args){Comparator<Integer> com = (x,y) -> {System.out.println(x); // 1System.out.println(y); // 5return Integer.compare(x,y);};int i = com.compare(1, 5);System.out.println(i); // -1
}

当Lambda体只有一条语句时,return与大括号若有,都可以省略

Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
int i = com.compare(1, 5);
System.out.println(i); // -1

4、函数式接口

4.1、如何理解函数式接口

  • Java从诞生起就一直倡导一切皆对象,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的星期和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,也即Java不但可以支持OOP还可以支持OOF(面向函数编程)
  • 在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Labda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口
  • 简单的说,在java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示
  • 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写

4.2、什么是函数式(Function)接口

  • 只包含一个抽象方法的接口,成为函数式接口
  • 你可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)
  • 我们可以在一个接口上使用==@FunctionalInterface==注解,这样做可以检查它是否是一个函数式接口。同时javadoc也会包含一条声明,说明这个接口是一个函数式接口
  • 在java.util.function包下定义了Java8的丰富的函数式接口

4.3、Java内置四大核心函数式接口

Java提供了四大核心函数式接口

  • Consumer:消费性接口。对类型为T的对象应用操作,包含方法:void accept(T t)
  • Supplier:供给型接口。返回类型为T的对象,包含方法:T get()
  • Function<T,R>:函数型接口。对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t)
  • Predicate:断定型接口。确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t)

在这里插入图片描述

Consumer

public static void main(String[] args){Consumer<String> con = s -> System.out.println(s);con.accept("hello world!"); // hello world!
}

Supplier

public static void main(String[] args){Supplier<String> sup = () -> "hello world";String s = sup.get();System.out.println(s); // hello world
}

Function<T,R>

public static void main(String[] args){// 输入类型为Integer类型,返回结果为String类型Function<Integer,String> fun = (a) -> String.valueOf(a);String apply = fun.apply(5201314);System.out.println(apply); // 5201314
}

Predicate

public static void main(String[] args){Predicate<String> pre = (s) -> s == null;boolean aaa = pre.test("aaa");System.out.println(aaa); // falseboolean test = pre.test(null);System.out.println(test); // true
}

4.4、其他接口

除了上面四大核心接口外,还提供了针对四大核心接口的增强接口,有需要的可以直接使用

在这里插入图片描述

5、方法引用

  • 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用

  • 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖

  • 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致

  • 如下三种主要使用情况

    • 对象::实例方法名

    • 类::静态方法名

    • 类::实例方法名

5.1、对象::实例方法名

// 情况一:对象::方法
// Consumer中的void accept(T t)
// PrintSteam中的void println(T t)
public static void main(String[] args){Consumer<String> con1 = a -> System.out.println(a);con1.accept("hello"); // helloSystem.out.println("*****************************");PrintStream out = System.out;// 对象::方法,结果和上面一样Consumer<String> con2  = out::println;con2.accept("world!"); // world
}

5.2、类::静态方法名

// 情况二:类::静态方法
// Comparator中的int compare(T o1, T o2)
// Integer中的static int compare(int x, int y)
public static void main(String[] args){Comparator<Integer> com = (x,y) -> x.compareTo(y);int i = com.compare(10, 20);System.out.println(i); // -1System.out.println("***************************");Comparator<Integer> com2 = Integer::compare;int i2 = com2.compare(10, 20);System.out.println(i2); // -1
}

5.3、类::实例方法名

// 情况二:类::实例方法
// Comparator中的int compare(T o1, T o2)
// Integer中的int compareTo(Integer anotherInteger)
// 虽然参数数量不一致,但是调用方法为这样结构的 o1.xxx(o2),可以写 o1的类名::o1要调用的方法
public static void main(String[] args){Comparator<Integer> com = (x,y) -> x.compareTo(y);int i = com.compare(10, 20);System.out.println(i); // -1System.out.println("***************************");Comparator<Integer> com2 = Integer::compareTo;int i2 = com2.compare(10, 20);System.out.println(i2); // -1
}

6、构造器引用

6.1、无参构造

public class Test{public static void main(String[] args){// Supplier<T>中的 T get()// Student中的 public Student() 无参构造Supplier<Student> sup = () -> new Student();System.out.println(sup.get()); // Student{name='null', age=null, birthday=null}// 构造引用写法Supplier<Student> sup2 = Student::new;System.out.println(sup2.get()); // Student{name='null', age=null, birthday=null}}
}class Student{private String name;private Integer age;private LocalDateTime birthday;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", birthday=" + birthday +'}';}public Student() {}public Student(String name, Integer age, LocalDateTime birthday) {this.name = name;this.age = age;this.birthday = birthday;}public Student(String name, Integer age) {this.name = name;this.age = age;}public Student(String name) {this.name = name;}
}

6.2、单参数构造

public class Test{public static void main(String[] args){// Function<T,R>中的 R apply(T t)// Student中的 public Student(String name) 单参构造Function<String,Student> fun = a -> new Student(a);Student apply = fun.apply("张三");System.out.println(apply); // Student{name='张三', age=null, birthday=null}// 构造引用写法Function<String,Student> fun2 = Student::new;Student apply1 = fun2.apply("李四");System.out.println(apply1); // Student{name='李四', age=null, birthday=null}}
}//... 下面实体类省略

6.2、双参数构造

public class Test{public static void main(String[] args){// BiFunction<T,U,R>中的 R apply(T t, U u)// Student中的 public Student(String name, Integer age) 双参构造BiFunction<String,Integer,Student> biFun1 = (a,b) -> new Student(a,b);Student apply = biFun1.apply("张三", 20);System.out.println(apply); // Student{name='张三', age=20, birthday=null}// 构造引用写法BiFunction<String,Integer,Student> biFun2 = Student::new;Student apply2 = biFun2.apply("李四", 25);System.out.println(apply2); // Student{name='李四', age=25, birthday=null}}
}
//... 下面实体类省略

6.3、三参数构造

三参构造我们上面讲解Java的函数式接口并没有提到,我也不知道,所以需要自己写一个函数式接口,满足业务需求

1、定义函数式接口

@FunctionalInterface
interface MyFunction<T,U,O,R>{R apply(T t, U u, O o);
}

2、使用自定义函数式接口

public static void main(String[] args){// MyFunction<T,U,O,R>中的 R apply(T t, U u, O o)// Student中的 public Student(String name, Integer age, LocalDateTime birthday) 三参构造MyFunction<String,Integer,LocalDateTime,Student> mf = (a,b,c) -> new Student(a,b,c);Student apply = mf.apply("张三", 20, LocalDateTime.now());System.out.println(apply); // Student{name='张三', age=20, birthday=2022-11-25T16:01:10.610}// 构造引用写法MyFunction<String,Integer,LocalDateTime,Student> mf2 = Student::new;Student apply2 = mf.apply("李四", 25, LocalDateTime.now());System.out.println(apply2); // Student{name='李四', age=25, birthday=2022-11-25T16:01:10.611}
}

7、数组引用

就把数组当成特殊的类,使用new关键字创建

public static void main(String[] args){// MyFunction<T,U,O,R>中的 R apply(T t, U u, O o)// Student中的 public Student(String name, Integer age, LocalDateTime birthday) 三参构造Function<Integer,String[]> fun = length -> new String[length];String[] strings = fun.apply(3);for (String string : strings) {/*nullnullnull*/System.out.println(string);}System.out.println("**********************************************");// 数组引用Function<Integer,String[]> fun2 = String[]::new;String[] strings2 = fun2.apply(4);for (String s : strings2) {/*nullnullnullnull*/System.out.println(s);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_36980.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot SpringBoot 原理篇 1 自动配置 1.2 bean 的加载方式【二】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.2 bean 的加载方式【二】1.2.1 第二种方式1 自动配置 1.2 bean …

Linux下Jenkins服务搭建及配置

一、简介 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;为软件的持续集成提供了一种便捷的方式。 二、Jenkins自动化部署实现原理 Jenkins的自动化部署实…

map容器(20221125)

一、map/multimap容器 1、map基本概念 map中所有元素都是pair&#xff1b; pair第一个元素为key&#xff08;键值&#xff09;,起到索引的作用&#xff0c;第二个元素为value(实值)&#xff1b; 所有元素会根据元素的键值&#xff08;key&#xff09;自动排序。 map/multi…

【自学前端】HTML篇已完结(附14节视频)

I have a dream,Front end development will not require additional training. 目录 内容预览 通过这里找视频&#xff1a; 1、内容仍然有所欠缺 2、目前以0基础再实战为主 3、目前未包含面试题 4、下一步的计划 5、希望收到反馈 内容预览 △ 目前纯HTML篇课程已经完成…

[足式机器人]Part3机构运动微分几何学分析与综合Ch02-2 平面机构离散运动鞍点综合——【读书笔记】

本文仅供学习使用 本文参考&#xff1a; 《机构运动微分几何学分析与综合》-王德伦、汪伟 《微分几何》吴大任 Ch02-2 平面机构离散运动鞍点综合2.3 鞍点圆2.3.1 鞍圆与二副连架杆R-R2.3.2 鞍圆误差2.3.3 四位置鞍圆2.3.4 五位置鞍圆2.3.5 多位置鞍圆2.3 鞍点圆 平面连杆机构中…

第五站:操作符(第二幕)

在前面的文章中我们详细讲解了操作符的一些内容&#xff0c; 今天我们来继续了解操作符剩余的内容 操作符第一幕的传送门在这&#xff1a;第五站&#xff1a;操作符&#xff08;第一幕&#xff09; 目录 七、关系操作符 八、逻辑操作符 1.基础知识 2.几道经典的题目 九、条…

手摸手教会你在idea中配置Tomcat进行servlet/jsp开发(多图超详)

1. 下载安装idea&#xff0c;创建project&#xff0c;如果没有JDK可以通过idea指定文件夹并下载JDK。工程就是普通的Java工程&#xff0c;名字为webdemo 2.因为是Web项目&#xff0c;所以要对这个普通的项目进行WEB扶持^^&#xff0c;在项目名称webdemo上右键单间选择菜单项&qu…

20221125使用PR2023自动识别obs-studio录屏生成的MKV视频的字幕

20221125使用PR2023自动识别obs-studio录屏生成的MKV视频的字幕 2022/11/25 19:07 01 obs.png obs studio &#xff08;64bit&#xff09; 02 obs 设置.png 03 obs 输出.png 04 obs默认为MKV.png 05 obs改mkv为MP4.png 警告&#xff1a;如果文件无法完成&#xff08;例如&…

嵌入式驱动初级-阻塞与非阻塞

文章目录前言一、五种IO模型二、阻塞与非阻塞三、多路复用前言 记录嵌入式驱动学习笔记 一、五种IO模型 当应用程序对设备驱动进行操作的时候&#xff0c;如果不能获取到设备资源&#xff0c;那么阻塞式 IO 就会将应用程 序对应的线程挂起&#xff0c;直到设备资源可以获取为止…

b站黑马JavaScript的Ajax案例代码——图书管理案例

目录 目标效果&#xff1a; 重点原理&#xff1a; 1.js数组操作中push方法 2.jquery中append方法 3.js数组操作中join方法 4.jQuery中attr方法 5.jQuery中trim方法 代码部分&#xff1a; 1. 图书管理案例.html(js部分全是重点&#xff0c;html部分用于看结构) 2.jquery.js…

mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)

mybatis复习05,mybatis的缓存机制&#xff08;一级缓存和二级缓存&#xff09;MyBatis的缓存机制MyBatis的一级缓存MyBatis的二级缓存二级缓存的相关配置MyBatis缓存查询的顺序整合第三方缓存EHCacheEHCache配置文件说明&#xff1a;MyBatis的缓存机制 MyBatis作为持久化框架&…

什么是DCS系统?DCS和SCADA的区别

如果你在工业自动化的企业环境中操作&#xff0c;可能听说过分布式控制系统 (DCS) 和监控和数据采集 (SCADA) 系统。 DCS系统和SCADA系统有很多共同点&#xff0c;因为它们都被称为受控计算机系统&#xff0c;接收和评估合法数据以实现远程访问监控和管理。 DCS(分布式控制系…

Flutter 中使用 extension 使项目更具可读性和效率 01

Flutter 中使用 extension 使项目更具可读性和效率 01 原文 https://medium.com/bedirhanssaglam/make-your-flutter-projects-more-readable-and-effective-with-extensions-b7dffd32e2f4 前言 代码的可读性和实用性在《 Flutter 》中非常重要。今天我们将编写一些 extension …

体系结构27_多处理机(1)

单处理机的发展正在走向尽头&#xff1f; 并行处理机在未来将会发挥更大的作用。 1.获得超过单处理器的性能&#xff0c;最直接的方法就是把多个处理器连在一起。 2.自1985年以来&#xff0c;体系结构的改进使性能迅速提高&#xff0c;这种改进的速度能否持续下去还不清楚&a…

信号类型(雷达)——雷达波形认识(一)

系列文章目录 《信号类型&#xff08;雷达通信&#xff09;》 文章目录 前言 简述 总结 前言 本文将结合个人研究经验&#xff0c;从雷达波形简单谈谈我对雷达的认识。之后将对常见的雷达波形进行简单分析。 简述 雷达的波形决定了信号处理的手段以及对应的雷达功能&#x…

体系结构29_多处理机的互联网络

互连网络是将集中式系统或分布式系统中的结点连接起来所构成的网络&#xff0c;这些结点可能是处理器、存储模块或者其它设备&#xff0c;它们通过互连网络进行信息交换。在拓扑上&#xff0c;互连网络为输入和输出两组结点之间提供一组互连或映象&#xff08;mapping&#xff…

【Linux】进程创建/终止/等待/替换

目录 一、子进程的创建 1、fork函数的概念 2、如何理解fork拥有两个返回值 3、fork调用失败的场景 二、进程的终止 1、main函数返回值 1.1main函数的返回值的意义 1.2将错误码转化为错误信息 1.3查看进程的退出码 2、进程退出的情况 1、进程的正常退出与异常退出 2…

Nodejs中包的介绍及npm安装依赖包的多种方法

文章目录1 包的介绍1.1 什么是包1.2 包的来源1.3 为什么需要包1.4 从哪里下载包1.5 如何下载包2 npm2.1 npm安装依赖包2.2 装包后多了哪些文件2.3 安装指定版本的包1 包的介绍 1.1 什么是包 Nodejs中的第三方模块又叫做包 就像电脑和计算机指的是相同的东西&#xff0c;第三…

推特自动发帖,全天占据核心流量

利用热门趋势和Hashtags标签 Twitter有一个热门趋势&#xff0c;跟微博热搜是差不多的&#xff0c;卖家可以多关注一下热门趋势&#xff0c;看看有没有和产品相关的内容。在帖子中加入趋势性和热门的标签&#xff0c;是一种非常好的营销方式。 这一方面能够增加推文的热度&am…

android源码-ContentProvider实现原理分析

前言&#xff1a; 最初的目的是想研究下ContentProvider产生ANR原因的&#xff0c;但是如果要讲ANR的原因&#xff0c;那么必须要了解ContentProvider的完整实现原理&#xff0c;所以本篇就先讲一下ContentProvider的实现原理&#xff0c;下一篇再去讲ANR的原因。 本篇主要会讲…