【jdk1.8特性】之Optional

简介Optional类是jdk1.8开始为我们提供的一个处理null的类。


代码实例说明

声明下面只示例介绍jdk1.8里Optional的用法,对于更高版本jdk里对Optional的进一步优化(如果有的话),
            这里不作介绍。

  • public T get()如果 Optional中存在值,则返回值,否则抛出 NoSuchElementException。

/**
 * .get()方法 : 如果 Optional中存在值,则返回值,否则抛出 NoSuchElementException
 *
 * @author JustryDeng
 * @date 2019/7/15 20:49
 */
@Test(expected = NoSuchElementException.class)
public void testFour() {
    Optional<?> optional = Optional.empty();
    optional.get();
}
  • public static <T> Optional<T> of(T value)获得持有value的Optional实例。

/**
 * .of(instance)方法 : 获得持有instance的Optional实例
 *
 * 注:instance不能为null
 *
 * @author JustryDeng
 * @date 2019/7/15 20:49
 */
@Test
public void testOne() {
    Staff staff = Staff.builder().name("员工9527").age(123).staffNo("NO.1").build();
    Optional<Staff> optional = Optional.of(staff);
    Assert.assertEquals(optional.get(), staff);
}
  • public static <T> Optional<T> ofNullable(T value)获得持有value的Optional实例。

/**
 * .ofNullable(instance)方法 : 获得持有instance的Optional实例
 *
 * 注:instance可以为null,为null时,获得的就是Optional.empty()
 *
 * @author JustryDeng
 * @date 2019/7/15 20:49
 */
@Test(expected = NoSuchElementException.class)
public void testTwo() {
    Optional<Staff> optional = Optional.ofNullable(null);
    // 当optional不持有值的时候,调用 optional.get()方法会抛出NoSuchElementException
    // 注:Optional.empty()方法获得的Optional实例,就是不持有值的Optional实例
    optional.get();
}
  • public boolean isPresent()判断optional持有的值是否为null(即:判断Optional是否持有值)。

/**
 * .isPresent()方法 : 判断optional持有的值是否为null(即:判断Optional是否持有值)。
 * 官方的话是 : 如果存在值,则返回 true ,否则为 false 。
 *
 * @author JustryDeng
 * @date 2019/7/15 20:49
 */
@Test
public void testThree() {
    Staff staff = Staff.builder().name("员工9527").age(123).staffNo("NO.1").build();
    // 持有值时(即:Optional<T>中,T不为null时)
    Optional<Staff> optionalOne = Optional.ofNullable(staff);
    Assert.assertTrue(optionalOne.isPresent());
    // 不持有值时
    Optional<Staff> optionalTwo = Optional.ofNullable(null);
    Assert.assertFalse(optionalTwo.isPresent());
}
  • public void ifPresent(Consumer<? super T> consumer)如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。

class  MyConsumer implements Consumer<Staff>{
    @Override
    public void accept(Staff staff) {
        System.out.println("重新了accept(T t)方法 -> " + staff);
    }
}

/**
 * .ifPresent()方法 : 如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
 *
 * @author JustryDeng
 * @date 2019/7/15 21:06
 */
@Test
public void testFive() {
    Staff staff = Staff.builder().name("员工9527").age(123).staffNo("NO.1").build();
    Optional<Staff> optional = Optional.ofNullable(staff);
    optional.ifPresent(new MyConsumer());
    // 此处我们可以不需要显示的实现Consumer接口,而是直接使用lombda表达式来进行优化,如:
    // optional.ifPresent(s -> System.out.println("重新了accept(T t)方法 -> " + s));
    Optional<Staff> emptyOptional = Optional.empty();
    emptyOptional.ifPresent(k -> System.out.println("如果emptyOptional不持有值,那么是不会输出这句话的。"));
}
  • public Optional<T> filter(Predicate<? super T> predicate) : 如果一个值存在,并且该值给定的谓词相匹配时(即:filter(Predicate<? super T> predicate)里的,predicate判定结果为true时),返回一个 Optional描述的值,否则返回一个空的 Optional。

class  MyPredicate implements Predicate<Staff> {
    @Override
    public boolean test(Staff staff) {
        boolean result = staff != null && staff.getAge() > 100;
        log.info(" MyPredicate.test result is -> {}", result);
        return result;
    }
}

/**
 * .filter()方法 : 如果一个值存在,并且该值给定的谓词相匹配时(即:filter(Predicate<? super T> predicate)里的,
 *                predicate判定结果为true时),返回一个 Optional描述的值,否则返回一个空的 Optional 。
 *
 * @author JustryDeng
 * @date 2019/7/15 21:06
 */
@Test
public void testSix() {
    Staff staff = Staff.builder().name("员工9527").age(123).staffNo("NO.1").build();
    Optional<Staff> optionalOne = Optional.ofNullable(staff);
    // 匹配Predicate,那么会返回一个 Optional描述的值
    Optional<Staff> newOptionalOne = optionalOne.filter(new MyPredicate());
    // 此时newOptionalOne.isPresent()结果应该为true
    Assert.assertTrue(newOptionalOne.isPresent());

    Optional<Staff> optionalTwo = Optional.ofNullable(null);
    // 不匹配Predicate,那么会返回一个不持有值的Optional实例(即:optional持有的是null)
    Optional<Staff> newOptionalTwo = optionalTwo.filter((s) -> s != null && s.getAge() > 1000);
    // 此时newOptionalOne.isPresent()结果应该为false
    Assert.assertFalse(newOptionalTwo.isPresent());
}
  • public<U> Optional<U> map(Function<? super T, ? extends U> mapper)Optional的泛型(即:持有值 数据类型)转换。

class  MyFunction implements Function<String, Staff> {

    /**
     * 将String转换为Staff
     */
    @Override
    public Staff apply(String s) {
        return Staff.builder().name(s).build();
    }
}

/**
 * .map()方法 : Optional的泛型(即:持有值 数据类型)转换
 *
 * 注:如Optional<A>.map(Function<? super A, ? extends B> function)后会得到Optional<B>,其
 *    中function的apply方法中定义有从A转换到B的规则
 *
 * 注:会应用function转换的前提是,Optional<A>持有值;
 *
 * 注:如果Optional<A>没持有值,或者Optional<A>持有值,但经过function转换后的Optional<B>不持有值的话,那么
 *    会返回一个一个空的(即:不持有值的)Optional
 *
 * @author JustryDeng
 * @date 2019/7/15 21:06
 */
@Test
public void testSeven() {
    Optional<String> optionalOne = Optional.of("蚂蚁牙黑");
    // 将字符串Optional<String>转换为Optional<Staff>,即:将【蚂蚁牙黑】转换为Staff
    Optional<Staff> newOptionalOne = optionalOne.map(new MyFunction());
    Assert.assertEquals("蚂蚁牙黑", newOptionalOne.orElse(Staff.builder().build()).getName());
}

注:如Optional<A>.map(Function<? super A, ? extends B> function)后会得到Optional<B>,
       其中function的apply方法中定义有从A转换到B的规则。

注:会应用function转换的前提是,Optional<A>持有值。

注:如果Optional<A>没持有值,或者Optional<A>持有值,但经过function转换后的Optional<B>
       不持有值的话,那么会返回一个一个空的(即:不持有值的)Optional。

  • public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)Optional泛型(即:持有值 数据类型)转换。

class  MyFunctionTwo implements Function<String, Optional<Staff>> {

    /**
     * 将String转换为Optional<Staff>
     */
    @Override
    public Optional<Staff> apply(String s) {
        return Optional.of(Staff.builder().name(s).build());
    }
}

/**
 * .flatMap()方法 : Optional泛型(即:持有值 数据类型)转换
 *
 * 注:如Optional<A>.map(Function<? super A, ? extends B> function)后会得到Optional<B>,其
 *    中function的apply方法中定义有从A转换到B的规则
 *
 * 注:会应用function转换的前提是,Optional<A>持有值;
 *
 * 注:如果Optional<A>没持有值,或者Optional<A>持有值,但经过function转换后的Optional<B>不持有值的话,那么
 *    会返回一个一个空的(即:不持有值的)Optional
 *
 * @author JustryDeng
 * @date 2019/7/15 21:06
 */
@Test
public void testEight() {
    Optional<String> optionalOne = Optional.of("蚂蚁牙黑");
    // 将String转换为Optional<Staff>,即:将【蚂蚁牙黑】转换为Staff
    Optional<Staff> newOptionalOne = optionalOne.flatMap(new MyFunctionTwo());
    Assert.assertEquals("蚂蚁牙黑", newOptionalOne.orElse(Staff.builder().build()).getName());
}

注:如Optional<A>.map(Function<? super A, ? extends B> function)后会得到Optional<B>,其
       中function的apply方法中定义有从A转换到B的规则。

注:会应用function转换的前提是,Optional<A>持有值。

注:如果Optional<A>没持有值,或者Optional<A>持有值,但经过function转换后的Optional<B>不
       持有值的话,那么会返回一个一个空的(即:不持有值的)Optional。

  • public T orElse(T other)返回值如果存在,则返回该值;否则返回 other。

/**
 * public T orElse(T other) 返回值如果存在,则返回该值;否则返回 other。
 *
 * @author JustryDeng
 * @date 2019/7/16 9:44
 */
@Test
public void testNine() {
    Staff defaultStaff = Staff.builder().name("默认姓名").build();

    Staff staff = Staff.builder().name("邓二洋").build();
    Optional<Staff> optionalOne = Optional.of(staff);
    // 若optionalOne持有值,则返回值;若不持有值(相当于持有的值为null),则返回defaultStaff
    Staff s1 = optionalOne.orElse(defaultStaff);
    Assert.assertEquals("邓二洋", s1.getName());

    Optional<Staff> optionalTwo = Optional.ofNullable(null);
    // 若optionalTwo持有值,则返回值;若不持有值(相当于持有的值为null),则返回defaultStaff
    Staff s2 = optionalTwo.orElse(defaultStaff);
    Assert.assertEquals("默认姓名", s2.getName());
}
  • public T orElseGet(Supplier<? extends T> other)若optional持有值,则返回值;若不持有值(相当于持有的值为null),则调用other并返回该调用的结果。

class MySupplier implements Supplier<Staff> {

    @Override
    public Staff get() {
        return Staff.builder().name("李四").build();
    }
}
/**
 * public T orElseGet(Supplier<? extends T> other)
 * 若optional持有值,则返回值;若不持有值(相当于持有的值为null),则调用other并返回该调用的结果。
 *
 * 提示:可使用lombda进行优化
 *
 * @author JustryDeng
 * @date 2019/7/16 9:44
 */
@Test
public void testTen() {
    Staff staff = Staff.builder().name("邓二洋").build();
    Optional<Staff> optionalOne = Optional.of(staff);
    // 若optionalOne持有值,则返回值;若不持有值(相当于持有的值为null),则调用Supplier.get并返回该调用的结果
    Staff s1 = optionalOne.orElseGet(new MySupplier());
    Assert.assertEquals("邓二洋", s1.getName());

    Optional<Staff> optionalTwo = Optional.ofNullable(null);
    // 若optionalTwo持有值,则返回值;若不持有值(相当于持有的值为null),则调用Supplier.get并返回该调用的结果
    Staff s2 = optionalTwo.orElseGet(new MySupplier());
    Assert.assertEquals("李四", s2.getName());
}
  • public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。

class MySupplierTwo implements Supplier<RuntimeException> {

    @Override
    public RuntimeException get() {
        return null;
    }
}

/**
 * public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
 * throws X extends Throwable
 * 返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。
 *
 * 提示:可使用lombda进行优化
 *
 * @author JustryDeng
 * @date 2019/7/16 9:59
 */
@Test(expected = RuntimeException.class)
public void testEleven() {
    Staff staff = Staff.builder().name("邓二洋").build();
    Optional<Staff> optionalOne = Optional.of(staff);
    // 若optionalOne持有值,则返回值;若不持有值(相当于持有的值为null),则抛出由提供的供应商创建的异常。
    Staff s1 = optionalOne.orElseThrow(new MySupplierTwo());
    Assert.assertEquals("邓二洋", s1.getName());

    Optional<Staff> optionalTwo = Optional.ofNullable(null);
    // 若optionalTwo持有值,则返回值;若不持有值(相当于持有的值为null),则抛出由提供的供应商创建的异常。
    Staff s2 = optionalTwo.orElseThrow(new MySupplierTwo());
}
  • public boolean equals(Object obj)Optional重写了equals方法,会比较Optional持有对象的值。

/**
 * Optional重写了equals方法,会比较Optional持有对象的值
 */
@Test
public void testTwelve() {
    Staff staffOne = Staff.builder().name("邓二洋").age(25).build();
    Staff staffTwo = Staff.builder().name("邓二洋").age(25).build();
    Staff staffThree = Staff.builder().name("JustryDeng").age(25).build();

    // 第一个Optional
    Optional<Staff> optionalOne = Optional.of(staffOne);
    // 第二个Optional
    Optional<Staff> optionalTwo = Optional.of(staffTwo);
    // 第三个Optional
    Optional<Staff> optionalThree = Optional.of(staffThree);
    // 第四个Optional
    Optional<Staff> optionalFour = Optional.ofNullable(null);
    // 第五个Optional
    Optional<Staff> optionalFive = Optional.ofNullable(null);

    // true
    boolean resultOne = optionalOne.equals(optionalTwo);
    Assert.assertTrue(resultOne);
    // false
    boolean resultTwo = optionalOne.equals(optionalThree);
    Assert.assertFalse(resultTwo);
    // true(若两个Optional都不持有对象,那么这两个Optional进行equals的结果为true)
    boolean resultThree = optionalFour.equals(optionalFive);
    Assert.assertTrue(resultThree);
    // false
    boolean resultFour = optionalOne.equals(optionalFour);
    Assert.assertFalse(resultFour);
}
  • public int hashCode()返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。

/**
 * Optional.hashCode
 * 返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。
 */
@Test
public void testThirteen() {
    Staff staffOne = Staff.builder().name("邓二洋").age(25).build();
    Staff staffTwo = Staff.builder().name("邓二洋").age(25).build();
    Staff staffThree = Staff.builder().name("JustryDeng").age(25).build();

    // 第一个Optional
    Optional<Staff> optionalOne = Optional.of(staffOne);
    // 第二个Optional
    Optional<Staff> optionalTwo = Optional.of(staffTwo);
    // 第三个Optional
    Optional<Staff> optionalThree = Optional.of(staffThree);
    // 第四个Optional
    Optional<Staff> optionalFour = Optional.ofNullable(null);
    int resultOne = optionalOne.hashCode();
    log.info(" resultOne is -> 【{}】!", resultOne);
    int resultTwo = optionalTwo.hashCode();
    log.info(" resultTwo is -> 【{}】!", resultTwo);
    // 求Optional对象的hashCode,实际上求的是Optional持有的对象的hashCode
    Assert.assertEquals(resultOne, resultTwo);

    int resultThree = optionalThree.hashCode();
    Assert.assertNotEquals(resultOne, resultThree);

    int resultFour = optionalFour.hashCode();
    // 若Optional不持有值,那么hashCode值为0
    Assert.assertEquals(0, resultFour);
}
  • public String toString()返回此可选的非空字符串表示,适用于调试。

/**
 * Optional.toString
 * 返回此可选的非空字符串表示,适用于调试
 */
@Test
public void testFourteen() {

    Staff staffOne = Staff.builder().name("邓二洋").age(25).build();
    Optional<Staff> optionalOne = Optional.of(staffOne);

    Staff staffTwo = Staff.builder().name("JustryDeng").age(25).build();
    Optional<Staff> optionalTwo = Optional.of(staffTwo);

    Optional<Staff> optionalThree = Optional.ofNullable(null);
    // Optional[T.toString]
    log.info(" optionalOne is -> 【{}】!", optionalOne);
    // Optional[T.toString]
    log.info(" optionalTwo is -> 【{}】!", optionalTwo);
    // 若不持有值,那么tiString结果为 Optional.empty
    log.info(" optionalThree is -> 【{}】!", optionalThree);
}

 

提示一更多细节,可详见JDK API文档。

提示二本文只是示例的jdk1.8的Optional新特性,jdk1.9仍然对Optional有进一步优化,但本文这里并未示例。

 

^_^ 如有不当之处,欢迎指正

^_^ 参考文档
              
《jdk api 1.8_google.CHM》

^_^ 测试代码托管链接
               
https://github.com/JustryDeng…Jdk8Feature

^_^ 本文已经被收录进《程序员成长笔记(五)》,笔者JustryDeng

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值