- (1)基本概念22.1 Java8的新特性
- Stream接口的各项方法操作案例代码
// 1.准备一个List集合并放入Person类型的对象后打印
// 2.将List集合中所有成年人过滤出来并放入另外一个集合中打印
// 3.使用Stream接口实现上述功能
// 4.使用lambda表达式对上述代码进行优化
// 5.实现对集合中元素通过流跳过2个元素后再取3个元素后打印
// 6.实现集合中所有元素中的年龄获取出来并打印
// 7.实现集合中所有元素的自然排序并打印
// 8.判断集合中是否没有元素的年龄是大于45岁的
// 9.按照指定的比较器规则获取集合所有元素中的最大值
// 10.实现将集合中所有元素的年龄映射出来并进行累加后打印
// 11.实现将集合中所有元素的姓名映射出来并收集到集合中打印
- 22.1.6 Optional类
- (1)基本概念
- (2)常用的方法
(1)基本概念22.1 Java8的新特性
22.1.1 Java8的概述
Java8是 Java 语言的一个重要版本,该版本于2014年3月发布,是自Java5以来最具革命性的版本,这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。
22.1.2 函数式接口
函数式接口主要指只包含一个抽象方法的接口,如:java.lang.Runnable、java.util.Comparator接口等。
Java8提供@FunctionalInterface注解来定义函数式接口,若定义的接口不符合函数式的规范便会报错。
Java8中增加了java.util.function包,该包包含了常用的函数式接口,具体如下:
- 接口名称 方法声明 功能介绍
- Consumer void accept(T t) 根据指定的参数执行操作
- Supplier T get() 得到一个返回值
- Function
R apply(T t) 根据指定的参数执行操作并返回 [ ] Predicate boolean test(T t) 判断指定的参数是否满足条件
22.1.3 Lambda表达式
Lambda 表达式是实例化函数式接口的重要方式,使用 Lambda 表达式可以使代码变的更加简洁紧凑。
- lambda表达式:参数列表、箭头符号->和方法体组成,而方法体中可以是表达式,也可以是语句块。
- 语法格式:(参数列表) -> { 方法体; } - 其中()、参数类型、{} 以及return关键字 可以省略。
// 封装类**package **``**task22**``**;**``**public class **``**Person {**
** **``**private **``**String **``**name**``**;**``** private int **``**age**``**;**``** public **``**Person**``**() {**
** }**
** **``**public **``**Person**``**(String name**``**, int **``**age) {**
** **``**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**``**;**``** **``**}**
** **``**public void **``**show**``**(){**
** System.**``**_out_**``**.println(**``**"**``**没事出来**``**show**``**一下**``**"**``**)**``**;**``** **``**}**
** **``**@Override**``** **``**public **``**String **``**toString**``**() {**
** **``**return **``**"Person{" **``**+**
** **``**"name='" **``**+ **``**name **``**+ **``**'**``**\'**``**' **``**+**
** **``**", age=" **``**+ **``**age **``**+**
** **``**'}'**``**;**``** **``**}**
**}**
//实现类
`package ``task22``;``public class ``MethodReferenceTest {<br />
``public static void ``main``(String[] args) {<br />
``//1.``使用内名内部类 通过函数式接口``Runnable``中的方法实现``Person``类中的``show``方法`` ``Person person = ``new ``Person(``“``张飞``“``,``30``)``;`` ``Runnable runnable = ``new ``Runnable() {<br />
``@Override`` ``public void ``run``() {<br />
``person``.show()``;`` ``}<br />
}``;`` ``runnable.run()``;`` ``System.``out``.println(``“——————————“``)``;`` ``//2.``使用``lambda``表达式实现``person``类中的``show``方法`` ``Runnable runnable1 = () -> ``person``.show()``;`` ``runnable1.run()``;`` ``System.``out``.println(``“—————————“``)``;`` ``//3.``使用方法引用实现``person``类中的``show``方法的调用`` ``Runnable runnable2 = person::show``;`` ``runnable2.run()``;`` ``}<br />
}**`
22.1.4 方法引用
- 方法引用主要指通过方法的名字来指向一个方法而不需要为方法引用提供方法体,该方法的调用交给函数式接口执行。
- 方法引用使用一对冒号 :: 将类或对象与方法名进行连接,通常使用方式如下:
- 对象的非静态方法引用 ObjectName :: MethodName
- 类的静态方法引用 ClassName :: StaticMethodName
- 类的非静态方法引用 ClassName :: MethodName
- 构造器的引用 ClassName :: new
- 数组的引用 TypeName[] :: new
方法引用是在特定场景下lambda表达式的一种简化表示,可以进一步简化代码的编写使代码更加紧凑简洁,从而减少冗余代码。
22.1.5 Stream接口
案例题目:
准备一个List集合并放入Person类型的对象,将集合中所有成年人过滤出来放到另外一个集合并打印出来。
案例代码:
**package **``**task22**``**;**``**import **``**java.util.LinkedList**``**;**``**import **``**java.util.List**``**;**``**import **``**java.util.function.Consumer**``**;**``**import **``**java.util.function.Predicate**``**;**``**public class **``**ListPersoonTest {**
** **``**public static void **``**main**``**(String[] args) {**
** List<Person> list = **``**new **``**LinkedList<>()**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**张飞**``**"**``**,**``**30**``**))**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**小乔**``**"**``**,**``**17**``**))**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**周瑜**``**"**``**,**``**20**``**))**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**关羽**``**"**``**,**``**30**``**))**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**张飞**``**"**``**,**``**30**``**))**``**;**``** **``**list.add(**``**new **``**Person(**``**"**``**刘备**``**"**``**,**``**40**``**))**``**;**``** for **``**(Person tp:list) {**
** System.**``**_out_**``**.println(tp)**``**;**``** **``**}**
** System.**``**_out_**``**.println(**``**"-------------------------------------------------------"**``**)**``**;**``** **
方法声明
功能介绍
Optional reduce(BinaryOperator accumulator)
返回结合后的元素值** **``**List<Person> list1 = **``**new **``**LinkedList<>()**``**;**``** for **``**(Person tp : list) {**
** **``**if **``**(tp.getAge() >= **``**18**``**) {**
** list1.add(tp)**``**;**``** **``**}**
** }**
** **``**for **``**(Person tp : list1) {**
** System.**``**_out_**``**.println(tp)**``**;**``** **``**}**
** System.**``**_out_**``**.println(**``**"-------------------------------------------------------"**``**)**``**;**``** **``**// 3.**``**使用**``**Stream**``**接口实现上述功能**
** **``**list.stream().filter(**``**new **``**Predicate<Person>() {**
** **``**@Override**``** **``**public boolean **``**test**``**(Person person) {**
** **``**return **``**person.getAge() >= **``**18**``**;**``** **``**}**
** }).forEach(**``**new **``**Consumer<Person>() {**
** **``**@Override**``** **``**public void **``**accept**``**(Person person) {**
** System.**``**_out_**``**.println(person)**``**;**``** **``**}**
** })**``**;**``** **``**System.**``**_out_**``**.println(**``**"-------------------------------------------------------"**``**)**``**;**``** **``**// 4.**``**使用**``**lambda**``**表达式对上述代码进行优化**
** **``**//list.stream().filter(person -> person.getAge() >= 18).forEach(person -> System.out.println(person));**``** //**``**对**``**lambda**``**表达式进行优化**``** **``**list.stream().filter(person -> person.getAge() >= **``**18**``**).forEach(System.**``**_out_**``**::println)**``**;**``** **``**}**
**}**
(1)基本概念
java.util.stream.Stream接口是对集合功能的增强,可以对集合元素进行复杂的查找、过滤、筛选等操作。
Stream接口借助于Lambda 表达式极大的提高编程效率和程序可读性,同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势。
(2)使用步骤
创建Stream,通过一个数据源来获取一个流。
转换Stream,每次转换返回一个新的Stream对象。
对Stream进行聚合操作并产生结果。
(3)创建方式
方式一:通过调用集合的默认方法来获取流,如:default Stream stream()
方式二:通过数组工具类中的静态方法来获取流,如:static IntStream stream(int[] array)
方式三:通过Stream接口的静态方法来获取流,如:static Stream of(T… values)
方式四:通过Stream接口的静态方法来获取流,static Stream generate(Supplier<? extends T>s)
(4)中间操作
- 筛选与切片的常用方法如下:
方法声明 功能介绍
Stream fifilter(Predicate<? super T> predicate) 返回一个包含匹配元素的流
Stream distinct() 返回不包含重复元素的流
Stream limit(long maxSize) 返回不超过给定元素数量的流
Stream skip(long n) 返回丢弃前n个元素后的流
- 映射的常用方法如下:
方法声明 功能介绍
Stream map(Function<? super T,? extends R> mapper) 返回每个处理过元素组成的流
Stream flflatMap(Function<? super T,? extendsStream<? extends R>> mapper) 返回每个被替换过元素组成的流,并将所有流合成一个流
(5)终止操作
- 匹配与查找的常用方法如下:
方法声明 功能介绍
Optional fifindFirst() 返回该流的第一个元素
boolean allMatch(Predicate<? super T> predicate) 返回所有元素是否匹配
boolean noneMatch(Predicate<? super T> predicate) 返回没有元素是否匹配
Optional max(Comparator<? super T> comparator) 根据比较器返回最大元素
Optional min(Comparator<? super T> comparator) 根据比较器返回最小元素
long count() 返回元素的个数
void forEach(Consumer<? super T> action) 对流中每个元素执行操作
- 规约的常用方法如下:
方法声明 功能介绍
Optional reduce(BinaryOperator accumulator) 返回结合后的元素值
- 收集的常用方法如下:
方法声明 功能介绍
Stream接口的各项方法操作案例代码
**package com.lagou.task22;**
**import java.util.Comparator;**
**import java.util.LinkedList;**
**import java.util.List;**
**import java.util.Optional;**
**import java.util.function.BinaryOperator;**
**import java.util.function.Consumer;**
**import java.util.function.Function;**
**import java.util.function.Predicate;**
**import java.util.stream.Collectors;**
**public class ListPersonTest {**
** public static void main(String[] args) {**
// 1.准备一个List集合并放入Person类型的对象后打印
** List<Person> list = new LinkedList<>();**
** list.add(new Person("zhangfei", 30));**
** list.add(new Person("xiaoqiao", 17));**
** list.add(new Person("zhouyu", 20));**
** list.add(new Person("zhangfei", 30));**
** list.add(new Person("guanyu", 35));**
** list.add(new Person("liubei", 40));**
** for (Person tp: list) {**
** System.out.println(tp);**
** }**
** System.out.println("-------------------------------------------------------");**
// 2.将List集合中所有成年人过滤出来并放入另外一个集合中打印
** List<Person> list1 = new LinkedList<>();**
** for (Person tp : list) {**
** if (tp.getAge() >= 18) {**
** list1.add(tp);**
** }**
** }**
** for (Person tp : list1) {**
** System.out.println(tp);**
** }**
** System.out.println("-------------------------------------------------------");**
// 3.使用Stream接口实现上述功能
** list.stream().filter(new Predicate<Person>() {**
** @Override**
** public boolean test(Person person) {**
** return person.getAge() >= 18;**
** }**
** }).forEach(new Consumer<Person>() {**
** @Override**
** public void accept(Person person) {**
** System.out.println(person);**
** }**
** });**
** System.out.println("-------------------------------------------------------");**
// 4.使用lambda表达式对上述代码进行优化
** //list.stream().filter(person -> person.getAge() >= 18).forEach(person -> System.out.println(person));**
** list.stream().filter(person -> person.getAge() >= 18).forEach(System.out::println);**
** System.out.println("-------------------------------------------------------");**
// 5.实现对集合中元素通过流跳过2个元素后再取3个元素后打印
** list.stream().skip(2).limit(3).forEach(System.out::println);**
** System.out.println("-------------------------------------------------------");**
// 6.实现集合中所有元素中的年龄获取出来并打印
** list.stream().map(new Function<Person, Integer>() {**
** @Override**
** public Integer apply(Person person) {**
** return person.getAge();**
** }**
** }).forEach(System.out::println);**
** //list.stream().map(person -> person.getAge()).forEach(System.out::println);**
** list.stream().map(Person::getAge).forEach(System.out::println);**
** System.out.println("-------------------------------------------------------");**
// 7.实现集合中所有元素的自然排序并打印
** list.stream().sorted().forEach(System.out::println);**
** System.out.println("-------------------------------------------------------");**
// 8.判断集合中是否没有元素的年龄是大于45岁的
** boolean b1 = list.stream().noneMatch(new Predicate<Person>() {**
** @Override**
** public boolean test(Person person) {**
** return person.getAge() > 45;**
** }**
** });**
** System.out.println("b1 = " + b1); // true**
** b1 = list1.stream().noneMatch(person -> person.getAge() > 45);**
** System.out.println("b1 = " + b1); // true**
** System.out.println("-------------------------------------------------------");**
// 9.按照指定的比较器规则获取集合所有元素中的最大值
** Optional<Person> max = list.stream().max(new Comparator<Person>() {**
** @Override**
** public int compare(Person o1, Person o2) {**
** return o1.getAge() - o2.getAge();**
** }**
** });**
** System.out.println("按照年龄排序后的最大值是:" + max);**
** max = list.stream().max((o1, o2) -> o1.getAge() - o2.getAge());**
** System.out.println("按照年龄排序后的最大值是:" + max);**
** System.out.println("-------------------------------------------------------");**
// 10.实现将集合中所有元素的年龄映射出来并进行累加后打印
** Optional<Integer> reduce = list.stream().map(Person::getAge).reduce(new BinaryOperator<Integer>() {**
** @Override**
** public Integer apply(Integer integer, Integer integer2) {**
** return integer + integer2;**
** }**
** });**
** System.out.println("最终所有年龄的累加和是:" + reduce); // 172**
** //reduce = list.stream().map(Person::getAge).reduce(((integer, integer2) -> integer + integer2));**
** reduce = list.stream().map(Person::getAge).reduce((Integer::sum));**
** System.out.println("最终所有年龄的累加和是:" + reduce); // 172**
** System.out.println("-------------------------------------------------------");**
// 11.实现将集合中所有元素的姓名映射出来并收集到集合中打印
** list.stream().map(Person::getName).collect(Collectors.toList()).forEach(System.out::println);**
** }**
**}**
**
22.1.6 Optional类
案例题目
判断字符串是否为空,若不为空则打印字符串的长度,否则打印0。
(1)基本概念
java.util.Optional类可以理解为一个简单的容器,其值可能是null或者不是null,代表一个值存在或不存在。
该类的引入很好的解决空指针异常,不用显式进行空值检测。
(2)常用的方法
方法声明 功能介绍
static Optional ofNullable(T value) 根据参数指定数值来得到Optional类型的对象
Optional map(Function<? super T,? extends U>mapper )根据参数指定规则的结果来得到Optional类型的对象
T orElse(T other) 若该值存在就返回,否则返回other的数值。
案例代码
**package com.lagou.task22;**
**import java.util.Optional;**
**import java.util.function.Function;**
**public class OptionalTest {**
** public static void main(String[] args) {**
** //String str1 = "hello";**
** String str1 = null;**
** if (null != str1) {**
** System.out.println("字符串的长度是:" + str1.length()); // 5 空指针异常**
** } else {**
** System.out.println("字符串为空,因此长度为0!");**
** }**
** System.out.println("----------------------------------------------------");**
** **``** // Java8中使用Optional类实现空值的处理**
** // 1.将数据str1装到Optional对象代表的容器中**
** Optional<String> optional = Optional.ofNullable(str1);**
** **``** // 2.建立映射关系 使用字符串的长度与字符串建立映射关系**
** /*Optional<Integer> integer = optional.map(new Function<String, Integer>() {**
** @Override**
** public Integer apply(String s) {**
** return s.length();**
** }**
** });*/**
** //Optional<Integer> integer = optional.map(s -> s.length());**
** Optional<Integer> integer = optional.map(String::length);**
** **``**// 3.若字符串为空则打印0,否则打印字符串的数值**
** System.out.println("integer = " + integer); // Optional.empty**
** System.out.println(integer.orElse(0)); // 0**
** }**
**}**
``