Skip to content

Java进阶-Optional

写这篇文章的目的是提升自己对Optional类、Lambda表达式等知识的了解,在掌握了Java基础知识后,进入公司会发现有大量的Optional语句、Lambda表达式的写法,如果不加以掌握,阅读项目代码会非常吃力。

Optional类

为什么要有Optional类

null在编程中处理不好就会导致NullPointerException(空指针异常)。为了避免空指针移仓,代码中就会充斥着繁琐的Null检查和条件嵌套。Optional的出现帮我们解决了这个问题,它让我们可以更加安全、优雅地处理可能为空的值。

用法

of与empty

Optional.of()传入确切的值,不能为空;

Optional.empty()返回一个空的Optional对象;

orElse与orElseGet

Optional对象.orElse(new User()) 如果Optional对象里面为空,则返回新创建的对象;

Optional对象.orElseGet(() -> new User())

orElse()与orElseGet()功能上很相似,但是执行上有所不同;

对于orElse()不论Optional对象是否为空都会执行new User()这个方法,而对于orElseGet()只有Optional对象为空的时候才会去执行Supplier里面的方法;

如果获取默认值的代价比较高,使用orElseGet()是更好的选择,因为它只有在必要的时候才会执行;

public class Main {
    public static void main(String[] args) {
        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Matrix");
        User user = optionalUser.orElse(new User("taylor", "Taylor Swift"));
        System.out.println(user.getFullName());
    }
}

orElseThrow

orElseThrow()接收一个Supplier的函数式接口,通过实现该接口可以实现并抛出一个自定义异常;

optionalUser.orElseThrow(() -> new RuntimeException("User not found"));

ifPresent

ifPresent()接收一个Consumer的函数式接口作为参数,如果Optional对象含值则会执行lambda表达式里面的方法,如果Optional对象不含值的话,它将什么都不做。

optionalUser.ifPresent(user -> System.out.println(user.getFullName()));

ifPresentOrElse

ifPresentOrElse()如果希望值为空的时候,执行其它操作。

optionalUser.ifPresentOrElse(
                user -> System.out.println(user.getFullName()),
                () -> System.out.println("User not found")
);

filter

如果我们想要过滤Optional对象中的值,根据给定的条件来决定是否保留该值,我们可以使用Optional对象中的filter方法

Optional<User> optionalUser2 = optionalUser.filter(user -> user.getFullName().equals("Matrix"));

这里面如果user.getFullName().equals("Matrix")为true,则返回包含值的Optional对象,如果user.getFullName().equals("Matrix")为false,则返回一个空的Optional对象。

map

map()方法用于对Optional中的值进行转换,并返回一个新的Optional对象,其中包含了转换后的值;

当Optionalb包含值时,map就会接受function类型的参数,这个函数会被应用到Optional中的值上;如果Optional是空的,则map方法什么也不做,直接返回空的Optional对象。

optionalUser.map(user -> user.getFullName());
//可以使用方法引用的方式简化这个Lambda表达式
optionalUser.map(User::getFullName);

flapmap

flatMap用于合并嵌套的map对象,便于嵌套调用;

public Optional<String> getFullName(){
    return Optional.ofNullable(fullName);
}
//map和flatmap方法返回的数据类型是不一样的,flatMap会合并嵌套的Optional对象
Optional<Optional<String>> optionalOptionals = optionalUser.map(User::getFullName);
Optional<String> optionals = optionalUser.flatMap(User::getFullName);

Stream

Optional还提供了Stream方法,将Optional对象转化为Stream对象,然后对其中的值进行流操作;

如果Optional对象包含值,则将该值封装到Stream中,如果Optional对象为空,那么将创建一个空的Stream流。

Stream<String> a = optionalUser
        .map(User::getName)
        .stream();
a.forEach(System.out::println);

Optionalal不适用的场景

Optional不适用于类的字段中,会增加内存消耗,并且会使得对象的序列号变得复杂;

Optional不适用于方法的参数中,会使得方法的理解和使用变得复杂

Optional不适用于构造器参数

Optional不适用于集合的构造器参数

推荐学习课程:AlbertShen