java8新特性

文章目录


1.Java8新特性概述

java8的新特性有函数式接口、接口的默认方法与静态方法、Lambda表达式、方法引用与构造器引用、Stream API、新时间日期API、减少空指针异常Optional、支持重复注解、Fork/Join 框架等。

java8的优点如下:速度更快、代码更少(增加了新的语法Lambda表达式)、强大的Stream API、便于并行、最大化减少空指针异常Optional。

2.函数式接口

Lambda表达式需要函数式接口的支持,所以,我们有必要来说说什么是函数式接口。

  • 只有一个抽象方法的接口
  • 函数式接口上可以使用 @FunctionalInterface 注解也可以不使用
  • 函数式接口里可以定义默认方法:默认方法有方法体,不是抽象方法。
  • 函数式接口里可以定义静态方法:静态方法也不是抽象方法,是一个有具体方法实现的方法
  • 函数式接口里可以定义Object里的public方法(改成抽象方法):虽然它们是抽象方法,却不需要覆盖重写,因为所有接口的实现类都是Object类的子类,而在Object类中有这些方法的具体的实现。

2.1.函数式接口与lambda表达式的简单使用示例

例如下面使用函数式接口和Lambda表达式实现对字符串的处理功能。

定义函数式接口MyFunc,如下所示

java 复制代码
@FunctionalInterface
 public interface MyFunc <T> {
	 public T getValue(T t);
 }

接下来,定义一个操作字符串的方法,其中参数为MyFunc接口实例和需要转换的字符串。

java 复制代码
public String handlerString(MyFunc<String> myFunc, String str){
 	return myFunc.getValue(str);
 }

接下来,我们对自定义的函数式接口进行测试,此时我们传递的函数式接口的参数为Lambda表达式,并且将字符串转化为大写。

java 复制代码
@Test
 public void test6(){
	 String str = handlerString((s) -> s.toUpperCase(), "hello world");
	 System.out.println(str);
 }

也可以截取字符串的某一部分,如下所示:

java 复制代码
@Test
 public void test7(){
	 String str = handlerString((s) -> s.substring(0,4), "hello world");
	 System.out.println(str);
 }

通过handlerString(MyFunc myFunc, String str)方法结合Lambda表达式对字符串进行任意操作。
注意:作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型 。

2.2.四大核心函数式接口

函数式接口 参数类型 返回类型 使用场景
Consumer消费型接口 T void 对类型为T的对象应用操作,接口定义的方法:void accept(T t)
Supplier供给型接口 T 返回类型为T的对象,接口定义的方法:T get()
Function<T,R>函数式接口 T R 对类型为T的对象应用操作,并R类型的返回结果。接口定义的方法:R apply(T t)
Predicate断言型接口 T boolean 确定类型为T的对象是否满足约束条件,并返回boolean类型的数据。接口定义的方法:boolean test(T t)

2.2.1.Consumer接口

使用示例:

java 复制代码
public void handlerConsumer(Integer number, Consumer<Integer> consumer){
 	consumer.accept(number);
 }
 @Test
 public void test1(){
	 this.handlerConsumer(10000, (i) -> System.out.println(i));
 }

2.2.2. Supplier接口

使用示例:

java 复制代码
public List<Integer> getNumberList(int num, Supplier<Integer> supplier){
	 List<Integer> list = new ArrayList<>();
	 for(int i = 0; i < num; i++){
	 	list.add(supplier.get())
	 }
	 return list;
 }
 @Test
 public void test2(){
	 List<Integer> numberList = this.getNumberList(10, () -> new Random().nextInt(100));
	 numberList.stream().forEach(System.out::println);
 }

2.2.3. Function接口

使用示例:

java 复制代码
public String handlerString(String str, Function<String, String> func){
 	return func.apply(str);
 }
 @Test
 public void test3(){
	 String str = this.handlerString("binghe", (s) -> s.toUpperCase());
	 System.out.println(str);
 }

2.2.4. Predicate接口

使用示例:

java 复制代码
public List<String> filterString(List<String> list, Predicate<String> predicate)
 {
 	List<String> strList = new ArrayList<>();
	 for(String str : list){
		 if(predicate.test(str)){
		 	strList.add(str);
		 }
	 }
	 return strList;
 }
 @Test
 public void test4(){
	 List<String> list = Arrays.asList("Hello", "Lambda", "binghe", "lyz", "World");
	 List<String> strList = this.filterString(list, (s) -> s.length() >= 5);
	 strList.stream().forEach(System.out::println);
 }

2.3.其他函数接口

函数式接口 参数类型 返回类型 使用场景
BiFunction(T, U, R) T, U R 对类型为T,U的参数应用操作,返回R类型的结果。接口定义的方法:R apply(T t, U u)
UnaryOperator(Function子接口) T T 对类型为T的对象进行一 元运算, 并返回T类型的 结果。 包含方法为 T apply(T t)
BinaryOperator (BiFunction 子接口) T, T T 对类型为T的对象进行二 元运算, 并返回T类型的 结果。 包含方法为 T apply(T t1,T t2)
BiConsumer<T, U> T, U void 对类型为T, U 参数应用 操作。 包含方法为 void accept(T t, U u)
ToIntFunction T int 计算int值的函数
ToLongFunction T long 计算long值的函数
ToDoubleFunction T double 计算double值的函数
IntFunction int R 参数为int 类型的函数
LongFunction long R 参数为 long类型的函数
DoubleFunction double R 参数为double类型的函数

3.lambda表达式

Lambda表达式是一个匿名函数,本质上是对接口的实现,Lambda是一段可以传递的代码(能够做到将代码像数据一样进行传递)。

匿名内部类,例如,我们使用匿名内部类比较两个Integer类型数据的大小。

java 复制代码
Comparator<Integer> com = new Comparator<Integer>() {
	 @Override
	 public int compare(Integer o1, Integer o2) {
	 return Integer.compare(o1, o2);
	 }
 };

在上述代码中,我们使用匿名内部类实现了比较两个Integer类型数据的大小。

接下来,我们就可以将上述匿名内部类的实例作为参数,传递到其他方法中了,如下所示。

java 复制代码
TreeSet<Integer> treeSet = new TreeSet<>(com)

使用Lambda表达式完成两个Integer类型数据的比较。

java 复制代码
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

3.1.Lambda表达式的语法

Lambda表达式在Java语言中引入了 "->" 操作符, "->" 操作符被称为Lambda表达式的操作符或者箭头操作符,它将Lambda表达式分为两部分:

  • 左侧部分指定了Lambda表达式需要的所有参数。
    Lambda表达式本质上是对接口的实现,Lambda表达式的参数列表本质上对应着接口中方法的参数列表。
  • 右侧部分指定了Lambda体,即Lambda表达式要执行的功能。
    Lambda体本质上就是接口方法具体实现的功能。

常用的Lambda表达式的语法总结如下。
1.语法格式一:无参,无返回值,Lambda体只有一条语句

java 复制代码
Runnable r = () -> System.out.println("Hello Lambda");

2.语法格式二:Lambda表达式需要一个参数,并且无返回值

java 复制代码
Consumer<String> func = (s) -> System.out.println(s);

3.语法格式三:Lambda只需要一个参数时,参数的小括号可以省略

java 复制代码
Consumer<String> func = s -> System.out.println(s);

4.语法格式四:Lambda需要两个参数,并且有返回值

java 复制代码
BinaryOperator<Integer> bo = (a, b) -> {
 System.out.println("函数式接口");
 return a + b;
 };

5.语法格式五:当Lambda体只有一条语句时,return和大括号可以省略

java 复制代码
BinaryOperator<Integer> bo = (a, b) -> a + b;

6.语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器能够通过上下文推断出数据类型,这就是"类型推断"

java 复制代码
 BinaryOperator<Integer> bo = (Integer a, Integer b) -> {
 return a + b;
 };

等同于

java 复制代码
BinaryOperator<Integer> bo = (a, b) -> {
 return a + b;
 };

上述 Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的"类型推断"。

4.方法引用

5.Stream API概述

6.Optional类介绍

一个容器对象,它可以或可能不包含非空值。用于尽量避免空指针异常。

  • Optional.of(T t) : 创建一个 Optional 实例
  • Optional.empty() : 创建一个空的Optional 实例
  • Optional.ofNullable(T t):若 t 不为 null,创建 Optional实例,否则创建空实例
  • isPresent() : 判断是否包含值
  • orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
  • orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
  • map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
  • flatMap(Function mapper):与 map 类似,要求返回值必须是Optional

7.新时间日期API

8. JDK8 HashMap

  • JDK7 HashMap结构为数组+链表(发生元素碰撞时,会将新元素添加到链表开头)
  • JDK8 HashMap结构为数组+链表+红黑树(发生元素碰撞时,会将新元素添加到链表末尾,当HashMap总容量大于等于64,并且某个链表的大小大于等于8,会将链表转化为红黑树(注意:红黑树是二叉树的一种))
    JDK8 HashMap重排序:如果删除了HashMap中红黑树的某个元素导致元素重排序时,不需要计算待重排序的元素的HashCode码,只需要将当前元素放到(HashMap总长度+当前元素在HashMap中的位置)的位置即可。
相关推荐
新手小袁_J5 分钟前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅6 分钟前
C#关键字volatile
java·redis·c#
Monly217 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
Ttang239 分钟前
Tomcat原理(6)——tomcat完整实现
java·tomcat
钱多多_qdd20 分钟前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
waicsdn_haha22 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_192849990632 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
Code_流苏34 分钟前
VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)
java·ide·vscode·搭建·java开发环境
禁默1 小时前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架