Java8新特性之Lambda表达式、函数式接口、方法引用、Stream API、Optional类等的使用

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Java8新特性之Lambda表达式、函数式接口、方法引用、Stream API、Optional类等的使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Lambda表达式

Lambda表达式(lambda expression)是一个匿名函数,简化调用匿名函数的过程。

在Java 8语言中引入的一种新的语法元素和操作符: -> , 被称为Lambda操作符箭头操作符

它将Lambda分为两个部分:

1.指定Lambda表达式需要的参数列表

2.指定Lambda体,是抽象方法的实现逻辑,也即Lambda表达式要执行的功能

示例

public static void main(String[] args) {
    // 使用new的实现类的形式调用接口
    TestService testSerivce1 = new TestSerivceImpl();
    testSerivce1.test();
    
    // 使用匿名内部接口调用
    new TestService() {
        @Override
        public void test() {
            System.out.println("使用匿名内部类的形式调用接口");
        }
    }.test();
    
    // 使用lambda调用接口
    TestService testSerivce2=  ()-> System.out.println("使用lambda调用接口");
    testSerivce2.test();
}

使用Lambda表达式的前提:

必须是函数接口,即在该接口中只能存在一个抽象方法,该接口称作为函数接口

Lambda的具体使用

无参、无返回值

public static void main(String[] args) {
		Runnable runnable1 = new Runnable(){
			@Override
			public void run() {
				System.out.println("常规写法...");
			}
		};

		System.out.println("------------------------");
		
		Runnable runnable2=()->{
			System.out.println("Lambda表达式:无参,无返回值");
		};
		runnable1.run();
		runnable2.run();
	}

有参数、无返回值

public static void main(String[] args) {
		Consumer<String> consumer1 = new Consumer<String>() {
			@Override
			public void accept(String str) {
				System.out.println(str);
			}
		};
		consumer1.accept("常规写法...");

		System.out.println("------------------------");

		Consumer<String> consumer2 = (String str) -> {
			System.out.println(str);
		};
		consumer2.accept("Lambda需要一个参数,但是没有返回值");
	}

有参数,有返回值

    public static void main(String[] args) {
        Comparator<Integer> comparator1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };

        System.out.println(comparator1.compare(1, 2));

        System.out.println("------------------------");

        Comparator<Integer> comparator2 = (o1, o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(comparator2.compare(3, 2));
    }

省略数据类型

数据类型可以省略,由编译器进行类型推断得出

Consumer<String> consumer3 = (str) -> {
			System.out.println(str);
		};
		consumer3.accept("Lambda数据类型可以省略");

省略参数的小括号

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

Consumer<String> consumer3 = str -> {
			System.out.println(str);
		};
consumer3.accept("Lambda只需要一个参数时, 参数的小括号可以省略");

省略参数的小括号与Lambda体大括号

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

Consumer<String> consumer3 = str ->  System.out.println(str);
consumer3.accept("当Lambda体只有一条语句时,return号与大括号都可以省略");

函数式接口

只包含一个抽象方法的接口,称为函数式接口。

可以在一个接口上使用 @FunctionalInterface 注解,检查是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

Lambda表达式就是一个函数式接口的实例,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示

Java8提供了丰富的函数式接口

内置4大核心函数式接口

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

其他接口

函数式接口 参数类型 返回类型 用途
BiFunction<T, U, R> T, U R 对类型为T, U 参数操作,返回 R 类型的结果。方法: R apply(T t, U u)
UnaryOperator<T> (Function 子接口) T T 对类型为T的对象进行一元运算,并返回T类型的结果。方法:T apply(T t)
BinaryOperator<T> (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)
BiPredicate<T,U> T,U boolean 方法: boolean test(T t,U u)
ToIntFunction<T> T int 计算int值的函数
ToLongFunction<T> T long 计算long值的函数
ToDoubleFunction<T> T double 计算double值的函数
IntFunction<R> int R 参数为int类型的函数
LongFunction<R> long R 参数为long类型的函数
DoubleFunction<R> double R 参数为double类型的函数

使用Java提供的函数式接口

 public static void main(String[] args) {
        Fun(200, new Consumer<Integer>() {
            @Override
            public void accept(Integer money) {
                System.out.println("买东西,花费:" + money);
            }
        });
        Fun(200, (Integer money) -> System.out.println("买东西,花费:" + money));
    }

    public static void Fun(Integer money, Consumer<Integer> consumer) {
        consumer.accept(money);
    }
public static String Fun(Integer a, Function<Integer, String> function) {
        return function.apply(a);
    }

    public static void main(String[] args) {
        String str = Fun(100, new Function<Integer, String>() {
            @Override
            public String apply(Integer a) {
                return a * 2 + "";
            }
        });
        System.out.println(str);


        String str2 = Fun(100, (Integer a) -> a * 2 + "");
        System.out.println(str2);
    }

自定义函数式接口

不使用@FunctionalInterface

public interface MyFunctional {
    public void run();
}

使用@FunctionalInterface标识其是一个函数式接口

@FunctionalInterface
public interface MyFunctional {
    public void run();
}

使用泛型

@FunctionalInterface
public interface MyFunctional<T> {
    public String run(T t);
}

使用自定义函数式接口

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

  public static void Fun(MyFunctional<String> functional, String msg) {
        System.out.println(functional.run(msg));
    }

    public static void main(String[] args) {
        Fun(str -> str.length() + "", "hello world");
    }

方法引用

概述

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

方法引用就是Lambda表达式,也就是函数式接口的一个实例,是Lambda表达式的一个语法糖,结合lambda表达式能够让代码变得更加精简

格式:使用操作符 ::将类、对象与方法名分隔开来

引入规则

方法引入实际上就是lambda表达式中直接引入的方法。

必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回类型保持一致。
类型 语法 对应lambda表达式
静态方法引用 Class::static method (args) -> 类名.static_method(args)
对象方法引用 Class::method (inst,args) -> 类名.method(args)
实例方法引用 instance::method (args) -> instance.method(args)
构造器引用 Class::new (args) -> new 类名(args)

示例如下 :

    public static void main(String[] args) {
        Supplier<User> userSupplier = new Supplier<User>() {
            @Override
            public User get() {
                return new User("userName", 20);
            }
        };

        Supplier<User> userSupplier1 = () -> new User("userName", 20);
        System.out.println(userSupplier1.get());

        Supplier<User> userSupplier2 = User::new;
        System.out.println(userSupplier2.get());
    }

1.对象 :: 实例方法

PrintStream类的println方法

 public static void main(String[] args) {
        Consumer<String> consumer1 = (String str) -> System.out.println(str);
        consumer1.accept("hello world");
        
        Consumer<String> consumer2 = System.out::println;
        consumer2.accept("hello world");
    }

自定义对象的getName方法

    public static void main(String[] args) {
        User user = new User("userName", 20);
        Supplier<String> userSupplier1 = () -> user.getName();
        System.out.println(userSupplier1.get());

        Supplier<String> userSupplier2 = user::getName;
        System.out.println(userSupplier2.get());
    }

    static class User {
        private String name;
        private Integer age;

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public Integer getAge() {
            return age;
        }
    }

2.类 :: 静态方法名

Function中的apply(T t)方法

    public static void main(String[] args) {
        Function<Integer, User> function = age -> new User("user", age);
        User user = function.apply(20);
        System.out.println(user);

        Function<String, User> function2 = User::new;
        User user1 = function2.apply("userName");
        System.out.println(user1);
    }

Integer中的parseInt()方法

    public static void main(String[] args) {
        Function<String, Integer> function1 = (String number) -> Integer.parseInt(number);
        Integer apply1 = function1.apply("100");
        System.out.println(apply1);

        Function<String, Integer> function2 = Integer::parseInt;
        Integer apply2 = function2.apply("200");
        System.out.println(apply2);
    }

3.类 :: 实例方法名

String中的equals()方法

	public static void main(String[] args) {
		BiPredicate<String,String> pre2 = String :: equals;
		System.out.println(pre2.test("abc","abcd"));
	}

自定义类User,使用其getName()方法

    @Test
    void contextLoads() {
        User initUser = new User("userName", 20);

        Function<User, String> userFunction1 = (User user) -> user.getName();
        System.out.println(userFunction1.apply(initUser));

        Function<User, String> userFunction2 = User::getName;
        System.out.println(userFunction2.apply(initUser));
    }


	 class User {
        private String name;
        private Integer age;

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }
    }

4.构造器引用

与函数式接口相结合,自动与函数式接口中方法兼容

把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致,且方法的返回值为构造器对应类的对象

1.ClassName::new

   @Test
    void contextLoads() {
        Function<Integer, User> userFunction1 = (Integer age) -> new User(age);
        User user = userFunction1.apply(22);
        System.out.println(user);

        Function<Integer, User> userFunction2 = User::new;
        User user2 = userFunction2.apply(22);
        System.out.println(user2);
    }


	class User {
        private String name;
        private Integer age;

        public User(Integer age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public Integer getAge() {
            return age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

2.type[] :: new
数组引用: 数组是一个特殊的类,写法与构造器引用一致

    public static void main(String[] args) {
        Function<Integer, String[]> function1 = length -> new String[length];
        String[] arr1 = function1.apply(5);
        System.out.println(Arrays.toString(arr1));


        Function<Integer, String[]> function2 = String[]::new;
        String[] arr2 = function2.apply(5);
        System.out.println(Arrays.toString(arr2));
    }

Stream API

概述

Stream可以对集合进行非常复杂的查找、过滤和映射数据等操作。

简单的说:Stream API 提供了一种高效且易于使用的处理数据的方式

Stream特点

Stream自身不会存储元素

Stream不会改变源对象,相反会返回一个持有结果的新Stream

Stream操作是延迟执行的。意味着会等到需要结果的时候才执行

Stream使用步骤

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

中间操作:一连串的中间操作构成一条链,对数据源的数据进行处理

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

创建Stream

1.通过集合

default Stream<E> stream() : 返回一个顺序流

default Stream<E> parallelStream() : 返回一个并行流
    public static void main(String[] args) {
        ArrayList<User> userArrayList = new ArrayList<>();
        userArrayList.add(new User("user1", 11));
        userArrayList.add(new User("user2", 22));
        userArrayList.add(new User("user3", 33));

        // 返回一个顺序流
        Stream<User> stream = userArrayList.stream();
        // 返回一个并行流
        Stream<User> userStream = userArrayList.parallelStream();
    }

2.通过数组

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

static <T> Stream<T> stream(T[] array): 返回一个流
int[] arr = new int[]{1, 2, 3, 4, 5, 6};

IntStream stream = Arrays.stream(arr);

3.通过Stream 的of()

调用Stream类静态方法 of()创建一个流,可以接收任意数量的参数

public static<T> Stream<T> of(T... values) : 返回一个流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

4.创建无限流

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

public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)


public static<T> Stream<T> generate(Supplier<T> s)
//遍历前10个偶数
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
// 取10个数
Stream.generate(Math::random).limit(10).forEach(System.out::println);

中间操作

多个中间操作可以连接起来形成一个 流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理。

1.筛选与切片

方法 描 述
filter(Predicate p) 接收 Lambda , 从流中排除某些元素
distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
  public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("user1", 11));
        list.add(new User("user2", 22));
        list.add(new User("user3", 33));

        // 返回一个顺序流
        Stream<User> stream = list.stream();

        //  filter(Predicate p)——接收 Lambda从流中排除某些元素。
        stream.filter(e -> e.getAge() > 20).forEach(System.out::println);
        System.out.println();

        //  limit(n)——截断流,使其元素不超过给定数量。
        list.stream().limit(2).forEach(System.out::println);
        System.out.println();

        //  skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        list.stream().skip(2).forEach(System.out::println);
        System.out.println();

        list.add(new User("user3", 33));
        //  distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
        list.stream().distinct().forEach(System.out::println);
    }
User(name=user2, age=22)
User(name=user3, age=33)

User(name=user1, age=11)
User(name=user2, age=22)

User(name=user3, age=33)

User(name=user1, age=11)
User(name=user2, age=22)
User(name=user3, age=33)

2.映射

方法 描 述
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream
mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
    public static void main(String[] args) {
   		List<Integer> intLst = Arrays.asList(1, 2, 3, 4);
        Stream<Integer> intStream = intLst.stream();
        
        intStream.mapToInt(item -> item * 2).forEach(System.out::println);
        
  
        List<String> list = Arrays.asList("aa", "bbb", "cc", "ddd");
        Stream<String> stream = list.stream();

        //  map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
        System.out.println();

        // 长度>3
        stream.filter(str -> str.length() > 2).forEach(System.out::println);
        System.out.println();

        //   flatMap(Function f)——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
        Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
        characterStream.forEach(System.out::println);
        System.out.println();

        Stream<Stream<Character>> streamStream = list.stream().map(item -> fromStringToStream(item));
        streamStream.forEach(s -> s.forEach(System.out::println));
    }

    /**
     * 字符串中字符转字符Stream
     */
    public static Stream<Character> fromStringToStream(String str) {
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

3.排序

方法 描 述
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
 public static void main(String[] args) {
        // 自然排序
        List<Integer> IntList = Arrays.asList(1, 8, 2, 4, 3, 0, 6, 9);
        IntList.stream().sorted().forEach(System.out::println);

        ArrayList<User> list = new ArrayList<>();
        list.add(new User("user1", 11));
        list.add(new User("user2", 22));
        list.add(new User("user3", 33));

        // 定制排序
        list.stream().sorted((e1, e2) -> {
            int ageValue = Integer.compare(e1.getAge(), e2.getAge());
            if (ageValue != 0) {
                return ageValue;
            } else {
                return -Double.compare(e1.getAge(), e2.getAge());
            }
        }).forEach(System.out::println);
    }

Stream的终止操作

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

流进行了终止操作后,不能再次使用

1.匹配与查找

方法 描 述
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 使用Collection接口需要用户去做迭代,称为外部迭代。Stream API使用内部迭代,自动做迭代操作。
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("user1", 11));
        list.add(new User("user2", 22));
        list.add(new User("user3", 33));

        // 检查是否匹配所有元素。
        boolean allMatch = list.stream().allMatch(e -> e.getAge() > 18);
        System.out.println(allMatch);

        // 检查是否至少匹配一个元素。
        boolean anyMatch = list.stream().anyMatch(e -> e.getAge() > 22);
        System.out.println(anyMatch);

        // 检查是否没有匹配的元素。
        boolean noneMatch = list.stream().noneMatch(e -> e.getName().startsWith("aa"));
        System.out.println(noneMatch);

        //  返回第一个元素
        Optional<User> employee = list.stream().findFirst();
        System.out.println(employee);

        //     返回当前流中的任意元素
        Optional<User> employee1 = list.parallelStream().findAny();
        System.out.println(employee1);

        // count——返回流中元素的总个数
        long count = list.stream().filter(e -> e.getAge() > 20).count();
        System.out.println(count);
        //   返回流中最大值
        Stream<Integer> salaryStream = list.stream().map(e -> e.getAge());
        Optional<Integer> maxSalary = salaryStream.max(Double::compare);
        System.out.println(maxSalary);

        // 回流中最小值
        Optional<User> user = list.stream().min((e1, e2) -> Double.compare(e1.getAge(), e2.getAge()));
        System.out.println(user);
        System.out.println();

        //  内部迭代
        list.stream().forEach(System.out::println);

        // 使用集合的遍历操作
        list.forEach(System.out::println);
    }

2.归约

方法 描 述
reduce(T iden, BinaryOperator b) 将流中元素反复结合起来,得到一个值。返回 T
reduce(BinaryOperator b) 将流中元素反复结合起来,得到一个值。返回 Optional
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("user1", 11));
        list.add(new User("user2", 22));
        list.add(new User("user3", 33));

        //  将流中元素反复结合起来,得到一个值。返回 T
        List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = intList.stream().reduce(0, Integer::sum);
        System.out.println(sum);

        // 将流中元素反复结合起来,得到一个值。返回 Optional<T>
        Stream<Integer> ageStream = list.stream().map(User::getAge);
        Optional<Integer> sumAge = ageStream.reduce((d1, d2) -> d1 + d2);
        System.out.println(sumAge.get());
    }

3.收集

Collector接口中方法的实现决定了如何对流执行收集的操

方法 描 述
collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("user1", 11));
        list.add(new User("user2", 22));
        list.add(new User("user3", 33));
        list.add(new User("user3", 33));

        List<User> userList = list.stream().filter(e -> e.getAge() > 20).collect(Collectors.toList());
        userList.forEach(System.out::println);
        System.out.println();

        Set<User> userSet = list.stream().filter(e -> e.getAge() > 22).collect(Collectors.toSet());
        userSet.forEach(System.out::println);
    }

Collectors

Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例

方法 返回类型 描述 示例
toList List 把流中元素收集到List .collect(Collectors.toList())
toSet Set 把流中元素收集到Set .collect(Collectors.toSet())
toCollection Collection 把流中元素收集到创建的集合 .collect(Collectors.toCollection(ArrayList::new))
counting Long 计算流中元素的个数 .collect(Collectors.counting())
summingInt Integer 对流中元素的整数属性求和 .collect(Collectors.summingInt(User::getAge))
averagingInt Double 计算流中元素Integer属性的平均值 list.stream().collect(Collectors.averagingInt(User::getAge))
summarizingInt IntSummaryStatistics 收集流中Integer属性的统计值。如:平均值 .collect(Collectors.summarizingInt(User::getAge))
joining String 连接流中每个字符串 list.stream().map(User::getName).collect(Collectors.joining())
maxBy Optional 根据比较器选择最大值 .collect(Collectors.maxBy(comparingInt(User::getAge)))
minBy Optional 根据比较器选择最小值 .collect(Collectors.minBy(comparingInt(User::getAge)))
reducing 归约产生的类型 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 .collect(Collectors.reducing(0, User::getAge, Integer::sum))
collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果转换函数 .collect(Collectors.collectingAndThen(Collectors.toList(), List::size))
groupingBy Map<K, List> 根据某属性值对流分组,属性为K,结果为List collect(Collectors.groupingBy(User::getAge))
partitioningBy Map<Boolean, List> 根据true或false进行分区 .collect(Collectors.partitioningBy(User::getName))

Optional类

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

Optional是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象

创建Optional类对象

Optional.of(T t) : 创建一个 Optional 实例,t必须非空

Optional.empty() : 创建一个空的 Optional 实例

Optional.ofNullable(T t) :t可以为null
    public static void main(String[] args) {
        User user = new User();
        Optional<User> userOptional = Optional.of(user);
        System.out.println(userOptional);

        Optional<Object> empty = Optional.empty();
        System.out.println(empty);

        Optional<User> optionalUser = Optional.ofNullable(null);
        System.out.println(optionalUser);
    }

判断Optional容器中是否包含对象

boolean isPresent() : 判断是否包含对象

void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。
    public static void main(String[] args) {
        User user = new User();
        Optional<User> userOptional = Optional.of(user);
        System.out.println(userOptional.isPresent());
    }

获取Optional容器的对象

T get(): 如果调用对象包含值,返回该值,否则抛异常

T orElse(T other) :如果有值则将其返回,否则返回指定的other对象

T orElseGet(Supplier<? extends T> other) : :如果有值则将其返回,否则返回由Supplier接口实现提供的对象

T orElseThrow(Supplier<? extends X> exceptionSupplier) : :如果有值则将其返回,否则抛出由Supplier接口实现提供的异常
    public static void main(String[] args) {
        Optional<User> userOptional = Optional.ofNullable(null);
        User user = userOptional.orElse(new User("user", 29));
        System.out.println(user);
    }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136947.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!