目录
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda 表达式的语法格式如下:
(parameters) -> expression
或 (parameters) ->{ statements; }
例如:
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- System.out.println("running");
- }
- }).start();
-
-
- //lambda表达式
-
- new Thread(
- ()-> System.out.println("running")
- ).start();
- Comparator<Integer> comparator=new Comparator<Integer>() {
- @Override
- public int compare(Integer o1, Integer o2) {
- return Integer.compare(o1,o2);
- }
- };
-
- int compare = comparator.compare(12, 13);
- System.out.println(compare);
-
- //****************************
- //lambda表达式
- Comparator<Integer> comparator2=(o1, o2) ->Integer.compare(o1,o2);
-
- //方法引用
- Comparator<Integer> comparator3=Integer::compare;
1. 函数式接口,不用知道方法名。
2.通过泛型得知参数类型,不用知道具体的数据类型
3. 直接返回调用的结果
函数式接口:接口中一定要只有一个抽象方法才可以这么写。这也是Java8在接口中引入静态和默认方法的原因。

格式:
->:Lambda操作符或箭头操作符
->左边: Lambda形参列表(其实就是接口中的抽象方法的形参列表)
->右边: Lambda体(其实就是重写的抽象方法的方法体)I
语法格式1:无参,无返回值
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- System.out.println("running");
- }
- }).start();
-
-
- //lambda表达式
-
- new Thread(
- ()-> System.out.println("running")
- ).start();
语法格式2:一个参数,无返回值
- Consumer<String> consumer=new Consumer<String>() {
- @Override
- public void accept(String s) {
- System.out.println(s);
- }
- };
- consumer.accept("普通的接口实现");
-
- //************************************
- Consumer<String> consumer2=(String s)->System.out.println(s);
- consumer2.accept("Lambda表达式");
语法格式3:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
- Consumer<String> consumer=new Consumer<String>() {
- @Override
- public void accept(String s) {
- System.out.println(s);
- }
- };
- consumer.accept("普通的接口实现");
-
- //************************************
- Consumer<String> consumer2=(s)->System.out.println(s); //因为泛型把类型定死了
- consumer2.accept("Lambda表达式");
语法格式4: Lambda若只需要一个参数,参数的小括号可以省略
- Consumer<String> consumer=new Consumer<String>() {
- @Override
- public void accept(String s) {
- System.out.println(s);
- }
- };
- consumer.accept("普通的接口实现");
-
- //************************************
- Consumer<String> consumer2=s->System.out.println(s); //单参数省略小括号
- consumer2.accept("Lambda表达式");
语法格式5:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值
- Comparator<Integer> comparator = new Comparator<Integer>() {
- @Override
- public int compare(Integer o1, Integer o2) {
- return o1.compareTo(o2);
- }
- };
-
- Comparator<Integer> comparator2=(o1, o2) -> {return o1.compareTo(o2); };
语法格式六:当Lambda体只有一条语句时,return 与大括号若有,都可以省略
- Comparator<Integer> comparator = new Comparator<Integer>() {
- @Override
- public int compare(Integer o1, Integer o2) {
- return o1.compareTo(o2);
- }
- };
-
- Comparator<Integer> comparator2=(o1, o2) -> o1.compareTo(o2);
- }
* 总结:
* ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略
* ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字
Lambda表达式的本质:作为函数式接口的实例
如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。
我们可以在一个接口上使用 @FunctionalInterface注解 这样做可以检查它是否是一个函数式接口。
- /**
- * 自定义函数式接口
- */
- public interface MyInterFace {
-
- void method();
-
- // void method2();
-
- }

JDK 1.8 之前已有的函数式接口:
JDK 1.8 新增加的函数接口:

四大函数式接口_m0_46493091的博客-CSDN博客_四大函数式接口
- 对象::实例方法名
- 类::静态方法名
- 类::实例方法名
- // 情况一:对象 :: 实例方法
- //Consumer中的void accept(T t)
- //PrintStream中的void println(T t)
- @Test
- public void test() {
- Consumer<String> c1 = str -> System.out.println(str);
- c1.accept("苏州");
-
- System.out.println("+++++++++++++");
- PrintStream ps = System.out;
- Consumer<String> c2 = ps::println; //对象::实例方法名
- c2.accept("xian");
- }
- // 情况二:类 :: 静态方法
- //Comparator中的int compare(T t1,T t2)
- //Integer中的int compare(T t1,T t2)
- @Test
- public void test3() {
- Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1,t2);
- System.out.println(com1.compare(21,20));
-
- System.out.println("+++++++++++++++");
-
- Comparator<Integer> com2 = Integer::compare;
- System.out.println(com2.compare(15,7));
- }
-
- // 情况三:类 :: 实例方法 (有难度)
- // Comparator中的int comapre(T t1,T t2)
- // String中的int t1.compareTo(t2)
- @Test
- public void test5() {
- Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
- System.out.println(com1.compare("abc","abd"));
-
- System.out.println("++++++++++++++++");
-
- Comparator<String> com2 = String :: compareTo;
- System.out.println(com2.compare("abd","abm"));
- }
-
- //BiPredicate中的boolean test(T t1, T t2);
- //String中的boolean t1.equals(t2)
- @Test
- public void test6() {
- BiPredicate<String,String> pre1 = (s1, s2) -> s1.equals(s2);
- System.out.println(pre1.test("MON","MON"));
-
- System.out.println("++++++++++++++++++++");
-
- BiPredicate<String,String> pre2 = String :: equals;
- System.out.println(pre2.test("MON","MON"));
- }
Stream流式计算,最主要是用来方便计算操作。
Stream用于进行计算,是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
Stream并不会存储数据。(就跟迭代器相同,它们都只是一个操作工具,不存储数据)
Stream并不会改变数据源,它会返回一个含有结果集的Stream。
Stream是延迟加载的,在需要结果时才执行。
1、创建一个流。
一个数据源(如:集合、数组),获取一个流
2、将初始流转换为其他流的中间操作,可能包含多个步骤。
一个中间操作链,对数据源的数据进行处理
3、终止操作,执行终止操作后才执行中间操作链,此后这个流就不能再使用了。
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
Employee.class
- public class Employee {
-
- private int id;
- private String name;
- private int age;
- private double salary;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- 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 double getSalary() {
- return salary;
- }
-
- public void setSalary(double salary) {
- this.salary = salary;
- }
-
- public Employee() {
- System.out.println("Employee().....");
- }
-
- public Employee(int id) {
- this.id = id;
- System.out.println("Employee(int id).....");
- }
-
- public Employee(int id, String name) {
- this.id = id;
- this.name = name;
- }
-
- public Employee(int id, String name, int age, double salary) {
-
- this.id = id;
- this.name = name;
- this.age = age;
- this.salary = salary;
- }
-
- @Override
- public String toString() {
- return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
-
- Employee employee = (Employee) o;
-
- if (id != employee.id)
- return false;
- if (age != employee.age)
- return false;
- if (Double.compare(employee.salary, salary) != 0)
- return false;
- return name != null ? name.equals(employee.name) : employee.name == null;
- }
-
- @Override
- public int hashCode() {
- int result;
- long temp;
- result = id;
- result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + age;
- temp = Double.doubleToLongBits(salary);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
- }
EmployeeData.class
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 提供用于测试的数据
- */
- public class EmployeeData {
-
- public static List
getEmployees() { - List
list = new ArrayList<>(); -
- list.add(new Employee(1001, "马化腾", 34, 6000.38));
- list.add(new Employee(1002, "马云", 12, 9876.12));
- list.add(new Employee(1003, "刘强东", 33, 3000.82));
- list.add(new Employee(1004, "雷军", 26, 7657.37));
- list.add(new Employee(1005, "李彦宏", 65, 5555.32));
- list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));
- list.add(new Employee(1007, "任正非", 26, 4333.32));
- list.add(new Employee(1008, "扎克伯格", 35, 2500.32));
-
- return list;
- }
- }
- /**
- * 测试Stream的实例化
- */
- public class Streamapi {
-
- //创建 Stream方式一:通过集合
- @Test
- public void test(){
- List<Employee> employees = EmployeeData.getEmployees();
-
- // default Stream
stream() : 返回一个顺序流,拿集合数据时会按顺序 - Stream<Employee> stream = employees.stream();
-
- // default Stream
parallelStream() : 返回一个并行流,类似于线程,无序 - Stream<Employee> parallelStream = employees.parallelStream();
- }
-
- //创建 Stream方式二:通过数组
- @Test
- public void test2(){
- int[] arr = new int[]{1,2,3,4,5,6};
- //调用Arrays类的static
Stream stream(T[] array): 返回一个流 - IntStream stream = Arrays.stream(arr);
-
- Employee e1 = new Employee(1001,"Hom");
- Employee e2 = new Employee(1002,"Nut");
- Employee[] arr1 = new Employee[]{e1,e2};
-
- Stream<Employee> stream1 = Arrays.stream(arr1);
- }
- //创建 Stream方式三:通过Stream的of()
- @Test
- public void test3(){
- Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
- }
-
- //创建 Stream方式四:创建无限流
- @Test
- public void test4(){
- // 迭代
- // public static
Stream iterate(final T seed, final UnaryOperator f) - //遍历前10个偶数
- Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
-
- // 生成
- // public static
Stream generate(Supplier s) - Stream.generate(Math::random).limit(10).forEach(System.out::println);
- }
- }
| 方法 | 描述 |
|---|---|
filter(Predicate p) | 接收Lambda ,从流中排除某些元素 |
distinct() | 筛选,通过流所生成元素的hashCode() 和equals() 去除重复元素 |
limit(long maxSize) | 截断流,使其元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n)互补 |
-
- import org.junit.Test;
-
- import java.util.List;
- import java.util.stream.Stream;
-
- /**
- * 测试Stream的中间操作
- */
- public class StreamAPITest2 {
-
- //1-筛选与切片
- @Test
- public void test(){
- List
list = EmployeeData.getEmployees(); - // filter(Predicate p)——接收 Lambda , 从流中排除某些元素。
- Stream
stream = list.stream(); - //练习:查询员工表中薪资大于7000的员工信息
- stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
-
- System.out.println("+++++++++++++++++++++++");
- // limit(n)——截断流,使其元素不超过给定数量。
- list.stream().limit(3).forEach(System.out::println);
- System.out.println("+++++++++++++++++++++++");
-
- // skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
- list.stream().skip(3).forEach(System.out::println);
-
- System.out.println("+++++++++++++++++++++++");
- // distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
-
- list.add(new Employee(1013,"李飞",42,8500));
- list.add(new Employee(1013,"李飞",41,8200));
- list.add(new Employee(1013,"李飞",28,6000));
- list.add(new Employee(1013,"李飞",39,7800));
- list.add(new Employee(1013,"李飞",40,8000));
-
- // System.out.println(list);
-
- list.stream().distinct().forEach(System.out::println);
- }
- }
可以这么理解:filter是排除,map是提取
-
- import org.junit.Test;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Stream;
-
- /**
- * 测试Stream的中间操作
- */
- public class StreamAPITest2 {
-
- //2-映射
- @Test
- public void test2(){
- // map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。
- List
list = Arrays.asList("aa", "bb", "cc", "dd"); - list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
-
- // 练习1:获取员工姓名长度大于3的员工的姓名。
- List
employees = EmployeeData.getEmployees(); - Stream
namesStream = employees.stream().map(Employee::getName); - namesStream.filter(name -> name.length() > 3).forEach(System.out::println);
- System.out.println();
-
- //练习2:
- Stream
> streamStream = list.stream().map(StreamAPITest2::fromStringToStream); -
- streamStream.forEach(s ->{
- s.forEach(System.out::println);
- });
- System.out.println("++++++++++++++++++++++");
- // flatMap(Function f)——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
- Stream
characterStream = list.stream().flatMap(StreamAPITest2::fromStringToStream); -
- characterStream.forEach(System.out::println);
- }
-
- //将字符串中的多个字符构成的集合转换为对应的Stream的实例
- public static Stream
fromStringToStream(String str){//aa - ArrayList
list = new ArrayList<>(); - for(Character c : str.toCharArray()){
- list.add(c);
- }
- return list.stream();
- }
-
- @Test
- public void test3(){
- ArrayList list1 = new ArrayList();
- list1.add(25);
- list1.add(33);
- list1.add(14);
-
- ArrayList list2 = new ArrayList();
- list2.add(51);
- list2.add(23);
- list2.add(61);
-
- // list1.add(list2); 四个元素
- list1.addAll(list2); //这才是六个元素
- System.out.println(list1);
- }
- }
| 方法 | 描述 |
|---|---|
sorted() | 产生一个新流,其中按自然顺序排序 |
sorted(Comparator com) | 产生一个新流,其中按比较器顺序排序 |
-
- import org.junit.Test;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Stream;
-
- /**
- * 测试Stream的中间操作
- */
- public class StreamAPITest2 {
-
- //3-排序
- @Test
- public void test4(){
- // sorted()——自然排序
- List
list = Arrays.asList(25,45,36,12,85,64,72,-95,4); - list.stream().sorted().forEach(System.out::println);
-
-
- //抛异常,原因:Employee没有实现Comparable接口,对象排序必须去实现Comparable接口
- // List
employees = EmployeeData.getEmployees(); - // employees.stream().sorted().forEach(System.out::println);
-
-
- // sorted(Comparator com)——定制排序
-
- List
employees = EmployeeData.getEmployees(); - employees.stream().sorted( (e1,e2) -> {
-
- int ageValue = Integer.compare(e1.getAge(),e2.getAge());
- if(ageValue != 0){
- return ageValue;
- }else{
- return -Double.compare(e1.getSalary(),e2.getSalary());
- }
-
- }).forEach(System.out::println);
- }
- }
| 方法 | 描述 |
|---|---|
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代(使用Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了) |
-
- import org.junit.Test;
-
- import java.util.List;
- import java.util.Optional;
- import java.util.stream.Stream;
-
- public class StreamAPITest3 {
- //1-匹配与查找
- @Test
- public void test(){
- List
employees = EmployeeData.getEmployees(); -
- // allMatch(Predicate p)——检查是否匹配所有元素。
- // 练习:是否所有的员工的年龄都大于18
- boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 23);
- System.out.println(allMatch);
-
- // anyMatch(Predicate p)——检查是否至少匹配一个元素。
- // 练习:是否存在员工的工资大于 10000
- boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 9000);
- System.out.println(anyMatch);
-
- // noneMatch(Predicate p)——检查是否没有匹配的元素。
- // 练习:是否存在员工姓“马”
- boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("马"));
- System.out.println(noneMatch);
-
- // findFirst——返回第一个元素
- Optional
employee = employees.stream().findFirst(); - System.out.println(employee);
-
- // findAny——返回当前流中的任意元素
- Optional
employee1 = employees.parallelStream().findAny(); - System.out.println(employee1);
- }
-
- @Test
- public void test2(){
- List
employees = EmployeeData.getEmployees(); -
- // count——返回流中元素的总个数
- long count = employees.stream().filter(e -> e.getSalary() > 4500).count();
- System.out.println(count);
-
- // max(Comparator c)——返回流中最大值
- // 练习:返回最高的工资:
- Stream
salaryStream = employees.stream().map(e -> e.getSalary()); - Optional
maxSalary = salaryStream.max(Double::compare); - System.out.println(maxSalary);
-
- // min(Comparator c)——返回流中最小值
- // 练习:返回最低工资的员工
- Optional
employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())); - System.out.println(employee);
- System.out.println();
-
- // forEach(Consumer c)——内部迭代
- employees.stream().forEach(System.out::println);
-
- //使用集合的遍历操作
- employees.forEach(System.out::println);
- }
- }
| 方法 | 描述 |
|---|---|
reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回Optional |
备注:map 和reduce 的连接通常称为map-reduce 模式,因Google 用它来进行网络搜索而出名。
- import github2.Employee;
- import github2.EmployeeData;
- import org.junit.Test;
-
- import java.util.Arrays;
- import java.util.List;
- import java.util.Optional;
- import java.util.stream.Stream;
-
- public class StreamAPITest3 {
-
- //2-归约
- @Test
- public void test3(){
- // reduce(T identity, BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 T
- // 练习1:计算1-10的自然数的和
- List
list = Arrays.asList(72,25,32,34,43,56,81,15,29,71); - Integer sum = list.stream().reduce(0, Integer::sum);
- System.out.println(sum);
-
- // reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。返回 Optional
- // 练习2:计算公司所有员工工资的总和
- List
employees = EmployeeData.getEmployees(); - Stream
salaryStream = employees.stream().map(Employee::getSalary); - // Optional
sumMoney = salaryStream.reduce(Double::sum); - Optional
sumMoney = salaryStream.reduce((d1,d2) -> d1 + d2); - System.out.println(sumMoney.get());
- }
- }
| 方法 | 描述 |
|---|---|
collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法 |
-
- import org.junit.Test;
-
- import java.util.Arrays;
- import java.util.List;
- import java.util.Optional;
- import java.util.Set;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
-
- public class StreamAPITest3 {
-
- //3-收集
- @Test
- public void test4() {
- // collect(Collector c)——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
- // 练习1:查找工资大于6000的员工,结果返回为一个List或Set
-
- List
employees = EmployeeData.getEmployees(); - List
employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList()); -
- employeeList.forEach(System.out::println);
-
- System.out.println("++++++++++++++++++");
-
- Set
employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet()); -
- employeeSet.forEach(System.out::println);
- }
- }
Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。
Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。isPresent()方法会返回true,调用get()方法会返回该对象。
Optional.of(T t): 创建一个Optional 实例,t必须非空;Optional.empty(): 创建一个空的Optional 实例Optional.ofNullable(T t):t可以为null
boolean isPresent() : 判断是否包含对象void ifPresent(Consumer super T> consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。获取Optional容器的对象:
T get(): 如果调用对象包含值,返回该值,否则抛异常T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。Boy.class
- public class Boy {
- private Girl girl;
-
- public Boy() {
- }
-
- public Boy(Girl girl) {
- this.girl = girl;
- }
-
- public Girl getGirl() {
- return girl;
- }
-
- public void setGirl(Girl girl) {
- this.girl = girl;
- }
-
- @Override
- public String toString() {
- return "Boy{" +
- "girl=" + girl +
- '}';
- }
- }
Girl.class
- public class Girl {
- private String name;
-
- public Girl() {
- }
-
- public Girl(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Girl{" +
- "name='" + name + '\'' +
- '}';
- }
- }
测试类
- import org.junit.Test;
- import java.util.Optional;
-
- /**
- * Optional类:为了在程序中避免出现空指针异常而创建的。
- *
- * 常用的方法:ofNullable(T t)
- * orElse(T t)
- */
- public class OptionalTest {
- /**
- * Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
- * Optional.empty() : 创建一个空的 Optional 实例
- * Optional.ofNullable(T t):t可以为null
- */
- @Test
- public void test(){
- Girl girl = new Girl();
- // girl = null;
- //of(T t):保证t是非空的,如t为空,会报空指针异常
- Optional
optionalGirl = Optional.of(girl); - }
-
- @Test
- public void test2(){
- Girl girl = new Girl();
- // girl = null;
- //ofNullable(T t):t可以为null,如果为空,会返回Optional.empty()
- Optional
optionalGirl = Optional.ofNullable(girl); - System.out.println(optionalGirl);
- //orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.
- //如果内部的t是空的,则返回orElse()方法中的参数t1.
- Girl girl1 = optionalGirl.orElse(new Girl(""));
- System.out.println(girl1);
- }
- }
应用场景
- import org.junit.Test;
- import java.util.Optional;
-
- /**
- * Optional类:为了在程序中避免出现空指针异常而创建的。
- *
- * 常用的方法:ofNullable(T t)
- * orElse(T t)
- */
- public class OptionalTest {
-
- @Test
- public void test3(){
- Boy boy = new Boy();
- boy = null;
- String girlName = getGirlName(boy);
- System.out.println(girlName);
- }
-
- private String getGirlName(Boy boy) {
- return boy.getGirl().getName();
- }
-
- //优化以后的getGirlName():
- public String getGirlName1(Boy boy){
- if(boy != null){
- Girl girl = boy.getGirl();
- if(girl != null){
- return girl.getName();
- }
- }
- return null;
- }
-
- @Test
- public void test4(){
- Boy boy = new Boy();
- boy = null;
- String girlName = getGirlName1(boy);
- System.out.println(girlName);
- }
-
- //使用Optional类的getGirlName():
- public String getGirlName2(Boy boy){
-
- Optional
boyOptional = Optional.ofNullable(boy); - //此时的boy1一定非空
- Boy boy1 = boyOptional.orElse(new Boy(new Girl("朱淑贞")));
-
- Girl girl = boy1.getGirl();
-
- Optional
girlOptional = Optional.ofNullable(girl); - //girl1一定非空
- Girl girl1 = girlOptional.orElse(new Girl("阿青"));
-
- return girl1.getName();
- }
-
- @Test
- public void test5(){
- Boy boy = null;
- boy = new Boy();
- boy = new Boy(new Girl("李清照"));
- String girlName = getGirlName2(boy);
- System.out.println(girlName);
- }
- }
总结:Optional就是把null当成了一个合法对象了,以前我们会用if语句来判空,现在可以用Optional中的orElse方法可以作为一个备用方法来考虑为空的情景并返回,就可以规避了空指针的问题。
