详解Java8 Optional类{最全}

1:Optional

  1.1 概述

  Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException),提供了一些的方法代替过去的if-else处理逻辑,并与Stream流结合提供一致性的函数式编程.

       注意: Optional 不支持Java本身提供的序列化与反序列化机制,也就是RPC不能使用Java提供的序列化机制


1.2 方法概览

   序号    

方法

方法说明
1
private Optional()
 无参构造,构造一个空Optional
2
private Optional(T value)
 根据传入的非空value构建Optional
3
public static<T> Optional<T> empty()
返回一个空的Optional,该实例的value为空
4  
public static <T> Optional<T> of(T value)
根据传入的非空value构建Optional,与Optional(T value)方法作用相同
5  
public static <T> Optional<T> ofNullable(T value)

 与of(T value)方法不同的是,ofNullable(T value)允许你传入一个空的value,

当传入的是空值时其创建一个空Optional,当传入的value非空时,与of()作用相同

6  
public T get()
 返回Optional的值,如果容器为空,则抛出NoSuchElementException异常
7  
public boolean isPresent()
 判断当家Optional是否已设置了值
8  
public void ifPresent(Consumer<? super T> consumer)
 判断当家Optional是否已设置了值,如果有值,则调用Consumer函数式接口进行处理
9  
public Optional<T> filter(Predicate<? super T> predicate)
 如果设置了值,且满足Predicate的判断条件,则返回该Optional,否则返回一个空的Optional
10  
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

 如果Optional设置了value,则调用Function对值进行处理,并返回包含处理后值的Optional,否则返回空Optional

11  
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
 与map()方法类型,不同的是它的mapper结果已经是一个Optional,不需要再对结果进行包装
12  
public T orElse(T other)
 如果Optional值不为空,则返回该值,否则返回other 
13
public T orElseGet(Supplier<? extends T> other)
如果Optional值不为空,则返回该值,否则根据other另外生成一个
14
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
throws X
如果Optional值不为空,则返回该值,否则通过supplier抛出一个异常
16 public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)    判断当家Optional是否已设置了值,如果有值,则调用Runable函数式接口进行处理
17  public Stream<T> stream() 将当前Optional 转换为诶Stream,如果值不存在则转换为empty stream ,存在则转换为包含值的流

2: 常用方法

     2.1 构造方法

  •   需要提前检查NPE 使用of方法
  •   不管情况直接构造 使用ofNULLable*()方法
    •   empty() 方法 前面方法间接使用了这个方法
@Test(expected = NoSuchElementException.class)
    public void whenCreateEmptyOptional_thenNull() {
        Optional<User> emptyOpt = Optional.empty();
        emptyOpt.get();// 没有值 将会抛出异常
    }
    
    @Test(expected = NullPointerException.class)
    public void test_of() {
        User user=null;
        Optional<User> optional = Optional.of(user);
    }
    
    @Test
    public void test_ofNuLLAble() {
        User user=null;
        Optional<User> optional = Optional.ofNullable(user);
        optional.orElse(new User());
        // 一般不使用 optional.get();
    }

    2.2 取得值

  •  get方法取不到值将会抛出异常NPE
  •    orElse系列方法,在null值的情况 将会提供默认值
// 取得值
    @Test
    public void test_getValue() {
        Optional<String> opt = Optional.ofNullable(null);
        String str = opt.get();
        String str2 = opt.orElse("Tom");
        Assert.assertEquals("Tom", str2);
        String str3 = opt.orElseGet(()->"Tom2");
        Assert.assertEquals("Tom2", str3);
    }

2.3 检查处理

// 检查处理
    @Test
    public void  test_Check() {
        Optional<String> opt = Optional.ofNullable(null);
        
        Assert.assertTrue(opt.isEmpty());
        Assert.assertFalse(opt.isPresent());//not null
        
        if(opt.isPresent()) {
            String string = opt.get().toUpperCase();
        }
        opt.ifPresent(x->x.toUpperCase()); //解决了if 问题 代码简洁
        
        // 内部是runable 不能返回值 所以值这个方法功能有限 但是可以执行一些耗时操作
        opt.ifPresentOrElse(x->x.toUpperCase(),()->System.out.println("sss"));
    }

2.4 返回值

@Test
    public void test_returnValue() {
        Optional<String> opt = Optional.ofNullable(null);
        
        Assert.assertEquals("Cat", opt.orElse("Cat"));
        Assert.assertEquals("Cat", opt.orElseGet(()->"Cat"));
        // or 为jdk9 新方法
        String str_tom = opt.or(()->Optional.of("Tom")).get();
        Assert.assertEquals("Tom", str_tom);
    }

2.5 返回异常

@Test(expected = NoSuchElementException.class)
    public void test_return_Exception() {
        Optional<String> opt = Optional.ofNullable(null);
        
        Assert.assertEquals("Cat", opt.orElseThrow());
        
        Assert.assertEquals("Cat", opt.orElseThrow(()->new NoSuchElementException()));
    }

2.6 转换 与过滤

@Test
    public void test_MapAndFilter() {
        String [] str= new String[] {"a","b","c","d","1"};
        Optional<String[]> opt = Optional.ofNullable(str);
        
        // filter
        String[] res = opt.filter(x->{
            for (String s : x) {
                if(s.contains("e")) {
                    return false;
                }
            }
            return true;
        }).get();
        System.out.println(Arrays.toString(res));
        // map 转大小
        List<String> list=new ArrayList<>();
        for(String x:str) {list.add(x);};
        
        Optional<String> map = Optional.ofNullable(list).map(x->x.iterator().next().toUpperCase());
        List<String> list2 = Optional.ofNullable(list).stream().
                flatMap(x->x.stream().map(y->y.toUpperCase())).collect(Collectors.toList());
        System.out.println(list2);
    }

2.7 链式操作

  •   支持链式操作,序列化滞后
@Test
    public void Test_ChainCollec() {
        Street street = new Street("武汉轻工大学", 5);
        Address address = new Address(street);
        Person person = new Person("Tom", 12,address );
        
        String string = Optional.ofNullable(person).
                  flatMap(u->u.getAddress())
                  .flatMap(p->p.getStreet())
                  .map(l->l.getStreetName())
                  .orElse("default");
        System.out.println(string);
         
        Address address2 = new Address(null); 
        Person person2 = new Person("Tom",      12,null); 
        String     s3 = Optional.ofNullable(person2).flatMap(u->u.getAddress())
                             .orElse(new Address(null))
                            .getStreet()
                            .orElse(new Street("武汉大学", 1))
                            .getStreetName();
        System.out.println(s3);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream obr;
        try {
            obr = new ObjectOutputStream(bos);
            obr.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
        try {
            ObjectInputStream inputStream2 = new ObjectInputStream(inputStream);
            Person person23 = (Person) inputStream2.readObject();
            System.out.println(person23.getAddress().get().getStreet().get().getStreetName());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

其他代码

class Person implements Serializable{
    private String name;
    private Integer age;
    private Address address;

    public Person(String name, Integer age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Optional<Address> getAddress() {
        return Optional.ofNullable(this.address);
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

class Address implements Serializable{
    private Street street ;

    public Optional<Street> getStreet() {
        return Optional.ofNullable(this.street);
    }
    public void setStreet(Street street) {
        this.street = street;
    }
    public Address(Street street) {
        super();
        this.street = street;
    }
}

class Street implements Serializable{
    private String streetName ;
    private Integer streetNo;

    public Street(String streetName, Integer streetNo) {
        this.streetName = streetName;
        this.streetNo = streetNo;
    }

    public String getStreetName() {
        return streetName;
    }

    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }

    public Integer getStreetNo() {
        return streetNo;
    }

    public void setStreetNo(Integer streetNo) {
        this.streetNo = streetNo;
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/dgwblog/p/11759665.html