java8--- Optional使用

if (person != null) {
    Country country = person.getCountry();
    if (country != null) {
        Province province = country.getProvince();
        if (province != null) {
            address = province.getCity();
        }
    }
}

1.第一种方法是不改变以前的entity:
   这里用Optional作为每一次返回的外壳,如果有某个位置返回了null,则会直接得到"unkonwn"。
    第一种方法可以平滑的和已有的JavaBean、Entity或POJA整合,而无需改动什么,也能更轻松的整合到第三方接口中(例如spring的bean)。建议目前还是以第一种Optional的使用方法为主,毕竟不是团队中每一个人都能理解每个get/set带着一个Optional的用意。
import java.util.Optional;
public class Test {
    public static void main(String[] args) {
        System.out.println(Optional.ofNullable(new Person())
            .map(x->x.country)
            .map(x->x.provinec)
            .map(x->x.city)
            .map(x->x.name)
            .orElse("unkonwn"));
    }
}
class Person {
    Country country;
}
class Country {
    Province provinec;
}
class Province {
    City city;
}
class City {
    String name;
}

第二种办法是将所有的值都用Optional来定义:

import java.util.Optional;
public class Test {
    public static void main(String[] args) {
        System.out.println(new Person()
                .country.flatMap(x -> x.provinec)
                .flatMap(Province::getCity)
                .flatMap(x -> x.name)
                .orElse("unkonwn"));
    }
}
class Person {
    Optional<Country> country = Optional.empty();
}
class Country {
    Optional<Province> provinec;
}
class Province {
    Optional<City> city;
    Optional<City> getCity(){//用于::
        return city;
    }
}
class City {
    Optional<String> name;
}
Optional还提供了一个filter方法用于过滤数据(实际上Java8里stream风格的接口都提供了filter方法)。例如过去我们判断值存在并作出相应的处理:

if(Province!= null){
  City city = Province.getCity();
  if(null != city && "guangzhou".equals(city.getName()){
    System.out.println(city.getName());
  }else{
    System.out.println("unkonwn");
  }
}
    现在我们可以修改为

Optional.ofNullable(province)
   .map(x->x.city)
   .filter(x->"guangzhou".equals(x.getName()))
   .map(x->x.name)
   .orElse("unkonw");
到此,利用Optional来进行函数式编程介绍完毕。Optional除了上面提到的方法,还有orElseGet、orElseThrow等根据更多需要提供的方法。orElseGet会因为出现null值抛出空指针异常,而orElseThrow会在出现null时,抛出一个使用者自定义的异常。可以查看API文档来了解所有方法的细节。
public class Test {
    public static void main(String[] args) {
        final String text = "Hallo world!";
        Optional.ofNullable(text)//显示创建一个Optional壳
            .map(Test::print)
            .map(Test::print)
            .ifPresent(System.out::println);

        Optional.ofNullable(text)
            .map(s ->{ 
                System.out.println(s);
                return s.substring(6);
            })
            .map(s -> null)//返回 null
            .ifPresent(System.out::println);
    }
    // 打印并截取str[5]之后的字符串
    private static String print(String str) {
        System.out.println(str);
        return str.substring(6);
    }
}
//Consol 输出
//num1:Hallo world!
//num2:world!
//num3:
//num4:Hallo world!

上面的代码中创建了2个Optional,实现的功能基本相同,都是使用Optional作为String的外壳对String进行截断处理。当在处理过程中遇到null值时,就不再继续处理。我们可以发现第二个Optional中出现s->null之后,后续的ifPresent不再执行。

注意观察输出的 //num3:,这表示输出了一个""字符,而不是一个null。
Optional提供了丰富的接口来处理各种情况,比如可以将代码修改为:

public class Test {
    public static void main(String[] args) {
        final String text = "Hallo World!";
        System.out.println(lowerCase(text));//方法一
        lowerCase(null, System.out::println);//方法二
    }

    private static String lowerCase(String str) {
        return Optional.ofNullable(str).map(s -> s.toLowerCase()).map(s->s.replace("world", "java")).orElse("NaN");
    }

    private static void lowerCase(String str, Consumer<String> consumer) {
        consumer.accept(lowerCase(str));
    }
}
//输出
//hallo java!
//NaN
这样,我们可以动态的处理一个字符串,如果在任何时候发现值为null,则使用orElse返回预设默认的"NaN"。

总的来说,我们可以将任何数据结构用Optional包裹起来,然后使用函数式的方式对他进行处理,而不必关心随时可能会出现的null。

https://yq.aliyun.com/articles/624440?spm=a2c4e.11153940.0.0.6a255562myIiAj


原文地址:https://www.cnblogs.com/hahajava/p/12193374.html