【技术创作101训练营】Java8新特性

方法

Java8新特性.pptx

开场白:

大家好,我叫小马哥,不是《英雄本色》中的那个小马哥,是一个想做个有钱人,却误入程序世界的小马哥。

很高兴能在云社区这样的好的平台下给大家分享一下我的经验,今天分享的主题是:Java8 新特性,为什么分享这个主题呢,20年jetbrains idea IDE 对Java 版本统计,java8 使用率 75%,但是对java8 新特性了解的人却不是很多,

分以下八个部分给大家分享一下。

  • java8新特性的简介
  • lambda表达式
  • 函数式接口
  • 方法引用和构造器引用
  • Stream API
  • 默认方法和静态方法
  • 新时间日期API
  • 其他新特性

一.java8新特性的简介 :

  1. 速度更快 (修改底层数据结构:如HashMap(数组-链表-红黑树),HashSet,ConcurrentHashMap(CAS算法)。 修改垃圾回收机制:取消堆中的永久区(PremGen)->回收条件苛刻,使用元空间(MetaSpace)->直接使用物理内存->加载类文件)
  2. 代码更少(增加了新的语法 Lambda 表达式)
  3. 强大的 Stream API (像操作数据库那样简单操作集合数据)
  4. 便于并行(并行更方便了)
  5. 最大化减少空指针异常 Optional

二.Lambda表达式 :

1.为什么使用 Lambda 表达式

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

2.Lambda 表达式语法

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

左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能

  • 语法格式一:无参,无返回值,Lambda 体只需一条语句

( ) -> System.out.println("我是一个无参数无返回值的方法 Lambda");

  • 语法格式二 :有一个参数,并且无返回值

( x ) -> System.out.println(x.length();

  • 语法格式三 :有一个参数,小括号可以省略

x -> System.out.println(x.length();

  • 语法格式四 :有两个以上参数,有返回值,并且 Lambda体 有多条语句

Comparator<Integer> com = (x,y) -> {

System.out.println("打印我一下");

return Integer.compare(x,y);

};

  • 语法格式五 :若 Lambda体中只有一条语句 ,return 和 大括号 都可以省略不写

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

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

(Integer x,Integer y) -> Integer.compare(x,y)

3.类型推断

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

三.函数式接口

1.什么是函数式接口

  • 只包含一个抽象方法的接口,称为函数式接口。
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方 法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解, 这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包 含一条声明,说明这个接口是一个函数式接口。

2.为什么要有函数式接口

在java中,一个lambda表达式相当于一个匿名内部类的实例对象,该对象能做什么由接口定义,具体怎么做在lambda里面写。之前写匿名内部类的时候感觉实在是太啰嗦了。java的lambda表达式其实就是一个匿名内部类里面,所有可以省略的东西都省略掉,就得到了一条非常简洁的lambda。

作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接 收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口 的类型。

3.Java 内置四大核心函数式接口

函数式接口

参数类型

返回类型

用户

Consumer
消费型接口

T

void

对类型为T的对象应用操作,包含方法: void accept(T t)

Supplier
供给型接口

void

T

返回类型为T的对象,包含方法: T get()

Consumer<T,R>
函数型接口

T

R

对类型为T的对象应用操作,并返回结果.结果的类型为R类型的对象,包含方法: R apply(T t)

Consumer
断言型接口

T

boolean

确定类型为T的对象是否满足某个约束,并对返回boolean 值.包含方法 boolean test(T t)

我们其实不用每次使用的时候都需要创建那么一个函数式接口,Java帮我们内置了这个四个接口,常用的基本就是这四个接口,其实还内置了其他的接口,这里就不一一列举了。

四.方法引用与构造器引用

1.方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用! (实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。 如下三种主要使用情况:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法

注意:

①Lamebda 体中 调用方法的参数列表与返回值得类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!

①若 Lamebda参数列表的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName :: Methd

2.构造器引用

格式: ClassName::new

与函数式接口相结合,自动与函数式接口中方法兼容。 可以把构造器引用赋值给定义的方法,与构造器参数 列表要与接口中抽象方法的参数列表一致!

3.数组引用

格式: type[] :: new

注意:Lamebda 体中 调用方法的参数列表与返回值得类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!

五.强大的 Stream API

1.了解 Stream

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一 个则是 Stream API(java.util.stream.*)。
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对 集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数 据库查询。也可以使用 Stream API 来并行执行操作。简而言之, Stream API 提供了一种高效且易于使用的处理数据的方式。

2.什么是 Stream

流(Stream) 到底是什么呢? 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 “集合讲的是数据,流讲的是计算!

注意:

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

3.Stream 的操作三个步骤

  • 创建 Stream

一个数据源(如:集合、数组),获取一个流

  • 中间操作

一个中间操作链,对数据源的数据进行处理

  • 终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果

4.创建 Stream

  • Java8 中的 Collection 接口被扩展

提供了两个获取流的方法 : stream()和parallelStream(),一个顺序流一个返回一个并行流

  • 由数组创建流

Java8 中的 Arrays 的静态方法 stream() 可 以获取数组流:

  • 由值创建流

可以使用静态方法 Stream.of(), 通过显示值 创建一个流。它可以接收任意数量的参数。

  • 由函数创建流:创建无限流

可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。

5.Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水 线上触发终止操作,否则中间操作不会执行任何的处理! 而在终止操作时一次性全部处理,称为“惰性求值” 。

  • 筛选与切片

方法

描述

filter(Predicate p)

接收 Lambda , 从流中排除某些元素。

distinct()

筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素

limit(long maxSize)

截断流,使其元素不超过给定数量。

skip(long n)

跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补

  • 排序

方法

描述

map(Function f)

接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。

mapToDouble(ToDoubleFunction f)

接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。

mapToInt(ToIntFunction f)

接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。

mapToLong(ToLongFunction f)

接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream。

flatMap(Function f)

接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流

  • 排序

方法

描述

sorted()

产生一个新流,其中按自然顺序排序

sorted(Comparator comp)

产生一个新流,其中按比较器顺序排序

6.Stream 的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。

  • 查找与匹配
  • 归约
  • 收集

7.并行流与串行流

  • 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
  • Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。

8.了解 Fork/Join 框架

  • 原理

Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个 小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总.

  • Fork/Join 框架与传统线程池的区别

采用 “工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线 程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。

相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的 处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因 无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果 某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子 问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程 的等待时间,提高了性能.

六.接口中的默认方法与静态方法

1.接口中的默认方法

Java 8中允许接口中包含具有具体实现的方法,该方法称为 “默认方法”,默认方法使用 default 关键字修饰。

接口默认方法的”类优先”原则

若一个接口中定义了一个默认方法,而另外一个父类或接口中 又定义了一个同名的方法时

  • 选择父类中的方法。如果一个父类提供了具体的实现,那么 接口中具有相同名称和参数的默认方法会被忽略。
  • 接口冲突。如果一个父接口提供一个默认方法,而另一个接 口也提供了一个具有相同名称和参数列表的方法(不管方法 是否是默认方法),那么必须覆盖该方法来解决冲突

2.接口中的静态方法

Java8 中,接口中允许添加静态方法。

七.新时间日期API

提供了 LocalDate、LocalTime、LocalDateTime LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日 历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信 息。也不包含与时区相关的信息。

注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法

1.Instant 时间戳

用于“时间戳”的运算。它是以Unix元年(传统

的设定为UTC时区1970年1月1日午夜时分)开始 所经历的描述进行运算

2.Duration 和 Period

Duration:用于计算两个“时间”间隔

Period:用于计算两个“日期”间隔

3.日期的操纵

TemporalAdjuster : 时间校正器。有时我们可能需要获 取例如:将日期调整到“下个周日”等操作。

TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

4.解析与格式化

java.time.format.DateTimeFormatter 类:该类提供了三种 格式化方法: 预定义的标准格式 语言环境相关的格式 自定义的格式

5.时区的处理

Java8 中加入了对时区的支持,带时区的时间为分别为: ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着 ID,地区ID都为 “{区域}/{城市}”的格式 例如 :Asia/Shanghai 等

ZoneId:该类中包含了所有的时区信息 getAvailableZoneIds() : 可以获取所有时区时区信息 of(id) : 用指定的时区信息获取 ZoneId 对象

八.其他新特性

1.Optional 类

Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在, 原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且 可以避免空指针异常。

2.重复注解与类型注解

Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。

总结:

  • lambda表达式
  • 函数式接口
  • 方法引用和构造器引用
  • Stream API
  • 默认方法和静态方法
  • 新时间日期API
  • 其他新特性

其中最为核心的为 Lambda 表达式与Stream API

谢谢大家!

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
【技术创作101训练营】Java8新特性
大家好,我叫小马哥,不是《英雄本色》中的那个小马哥,是一个想做个有钱人,却误入程序世界的小马哥。
<<上一篇
下一篇>>