Optionals不是函数式接口,而是用于尽量避免空指针异常的漂亮工具.

api


Optional.of(T t) : 创建一个 Optional 实例,建议不要使用,如果of里面的参数为null,会报空指针,建议直接用Optional.ofNullable

Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
Optional.empty() : 创建一个空的 Optional 实例

ifPresent(T value),就是value值不为空时,做的一些操作。
isPresent(T value),判断是否包含值

get() 获取值,如果Optional为空就会抛异常
orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional

代码案例

of

为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

  1. Optional<String> optional = Optional.of("xiaoming");
  2. //传入null,抛出NullPointerException
  3. Optional<Object> o = Optional.of(null);

ofNullable

为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

  1. Optional<Object> o1 = Optional.ofNullable(null);

isPresent

值存在返回true,否则返回false

  1. Optional<String> optiona2 = Optional.of("xiaoming");
  2. System.out.println(optiona2.isPresent());

ifPresent

如果Optional有值则调用consumer处理,否则不处理

  1. Optional<Object> o1 = Optional.ofNullable(null);
  2. o1.ifPresent(s -> System.out.println(s));

Java8之前写法:

  1. if(user!=null){
  2. dosomething(user);
  3. }

Java8写法:

  1. Optional.ofNullable(user)
  2. .ifPresent(u->{
  3. dosomething(u);
  4. });

get

Optional有值就返回,没有抛出NoSuchElementException

  1. Optional<Object> o1 = Optional.ofNullable(null);
  2. System.out.println(o1.get());

orElse

如果有值则将其返回,否则返回指定的其它值

  1. Optional<Object> o1 = Optional.ofNullable(null);
  2. System.out.println(o1.orElse("输出orElse")); // 输出orElse

orElseGet

orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值

  1. Optional<Object> o1 = Optional.ofNullable(null);
  2. System.out.println(o1.orElseGet(() -> "default value")); // default value

*注意:orElse 和 orElseGet 看似差不多,其实有很大不同;

当Optional 为空时,orElse和orElseGet 区别不大,但当Optional有值时,orElse仍然会去调用方法创建对象,而orElseGet不会再调用方法;在我们处理的业务数据量大的时候,这两者的性能就有很大的差异。

Java8之前写法

  1. public User getUser(User user) throws Exception{
  2. if(user!=null){
  3. String name = user.getName();
  4. if("zhangsan".equals(name)){
  5. return user;
  6. }
  7. }else{
  8. user = new User();
  9. user.setName("zhangsan");
  10. return user;
  11. }
  12. }

Java8之后的写法

  1. public User getUser(User user) {
  2. return Optional.ofNullable(user)
  3. .filter(u->"zhangsan".equals(u.getName()))
  4. .orElseGet(()-> {
  5. User user1 = new User();
  6. user1.setName("zhangsan");
  7. return user1;
  8. });
  9. }

orElseThrow

如果有值则将其返回,否则抛出supplier接口创建的异常。

以前写法

  1. public String getCity(User user) throws Exception{
  2. if(user!=null){
  3. if(user.getAddress()!=null){
  4. Address address = user.getAddress();
  5. if(address.getCity()!=null){
  6. return address.getCity();
  7. }
  8. }
  9. }
  10. throw new Excpetion("取值错误");
  11. }

用Java8写法

  1. public String getCity(User user) throws Exception{
  2. return Optional.ofNullable(user)
  3. .map(u-> u.getAddress())
  4. .map(a->a.getCity())
  5. .orElseThrow(()->new Exception("取指错误"));
  6. }

map

如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。

  1. Optional<String> optional = Optional.of("xiaoming");
  2. String s = optional.map(e -> e.toUpperCase()).orElse("shiyilingfeng");
  3. System.out.println(s); //输出: XIAOMING

flatMap

如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。与map不同的是,flatMap 的返回值必须是Optional,而map的返回值可以是任意的类型T

  1. Optional<String> optional = Optional.of("xiaoming");
  2. Optional<String> s = optional.flatMap(e -> Optional.of(e.toUpperCase()));
  3. System.out.println(s.get()); //输出:XIAOMING

map和flatMa两种区别是返回值区别.

  1. /**
  2. * map和flatMa两种区别是返回值区别.
  3. */
  4. @Test
  5. public void ceui_测试mapflatMap() {
  6. Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));
  7. //map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
  8. Optional<String> op2 = op.map(Employee::getName);//获取姓名
  9. System.out.println(op2.get());
  10. //flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
  11. Optional<String> op3 = op.flatMap(e -> Optional.of(e.getName()));//获取姓名
  12. System.out.println(op3.get());
  13. }

filter

filter(Predicate<? super T> predicate)

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

源码:

  1. public final class Optional<T> {
  2. //省略....
  3. Objects.requireNonNull(predicate);
  4. if (!isPresent())
  5. return this;
  6. else
  7. return predicate.test(value) ? this : empty();
  8. }

案例:

  1. List<String> strings = Arrays.asList("rmb", "doller", "ou");
  2. for (String s : strings) {
  3. Optional<String> o = Optional.of(s).filter(s1 -> !s1.contains("o"));
  4. System.out.println(o.orElse("没有不包含o的"));
  5. }

//输出:
rmb
没有不包含o的
没有不包含o的

  1. Optional<User> user1 = Optional
  2. .ofNullable(user)
  3. .filter(u -> u.getName().length()<6);

如上所示,如果 user 的 name 的长度是小于 6 的,则返回。如果是大于 6 的,则返回一个 EMPTY 对象。

是否会空指针的问题:

下面的 filter的案例2 会报空指针,其它的不会报空指针

  1. @Test
  2. public void filter的案例() {
  3. Employee employee = null;
  4. Employee rs = Optional.ofNullable(employee)
  5. .filter(a -> a.getName().equals("张三"))
  6. .orElse(null);
  7. System.out.println("rs = " + rs); // 返回null, 并不会空指针
  8. }
  9. @Test
  10. public void filter的案例2() {
  11. Employee employee = new Employee();
  12. Employee rs = Optional.ofNullable(employee)
  13. .filter(a -> a.getName().equals("张三"))//这里空指针
  14. .orElse(null);
  15. System.out.println("rs = " + rs);
  16. }
  17. @Test
  18. public void filter的案例3() {
  19. Employee employee = new Employee();
  20. Employee rs = Optional.ofNullable(employee)
  21. .filter(a -> "张三".equals(a.getName()))
  22. .orElse(null);
  23. System.out.println("rs = " + rs); // 返回null, 并不会空指针
  24. }
  25. @Test
  26. public void filter的案例4() {
  27. Employee employee = new Employee();
  28. employee.setName("张三");
  29. Employee rs = Optional.ofNullable(employee)
  30. .filter(a -> "张三".equals(a.getName()))
  31. .orElse(null);
  32. System.out.println("rs = " + rs); // 返回: Employee [id=0, name=张三, age=0, salary=0.0]
  33. }

代码案例

//of():为非null的值创建一个Optional
Optional<String> optional = Optional.of("bam");
// isPresent(): 如果值存在返回true,否则返回false
optional.isPresent();           // true
//get():如果Optional有值则将其返回,否则抛出NoSuchElementException
optional.get();                 // "bam"
//orElse():如果有值则将其返回,否则返回指定的其它值
optional.orElse("fallback");    // "bam"
//ifPresent():如果Optional实例有值则为其调用consumer,否则不做处理
optional.ifPresent((s) -> System.out.println(s.charAt(0)));     // "b"

import e_Lambda表达式.entity.Employee;
import e_Lambda表达式.j_Optional.entity.Godness;
import e_Lambda表达式.j_Optional.entity.Man;
import org.junit.Test;

import java.util.Optional;

/*
 * 一、Optional 容器类:用于尽量避免空指针异常
 *     Optional.of(T t) : 创建一个 Optional 实例
 *     Optional.empty() : 创建一个空的 Optional 实例
 *     Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
 *     isPresent() : 判断是否包含值
 *     orElse(T t) :  如果调用对象包含值,返回该值,否则返回t
 *     orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
 *     map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
 *     flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
 */
public class TestOptional {

    /**
     * 两种区别是返回值区别.
     */
    @Test
    public void ceui_测试map和flatMap() {
        Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));
        /*map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()*/
        Optional<String> op2 = op.map(Employee::getName);//获取姓名
        System.out.println(op2.get());
    /*flatMap(Function mapper):与 map 类似,要求返回值必须是Optional*/
        Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));//获取姓名
        System.out.println(op3.get());
    }

    @Test
    public void ceui_如果包含的对象有值就返回值_否则就返回自己默认的() {
        Optional<Employee> op = Optional.ofNullable(new Employee("张三"));
        /*如果包含的对象有值就返回值,否则就返回自己默认的*/
        Employee emp2 = op.orElseGet(() -> new Employee());
        System.out.println(emp2);
        System.out.println("-------------");

        Optional<Employee> op2 = Optional.ofNullable(null);
        /*如果包含的对象有值就返回值,否则就返回自己默认的*/
        Employee a = op2.orElseGet(() -> new Employee("我是默认值"));
        System.out.println(a);
    }

    @Test
    public void ceui_判断是否包含值() {
        Optional<Employee> op = Optional.ofNullable(new Employee());

        if (op.isPresent()) {//判断是否包含值
            System.out.println("包含值");
            System.out.println(op.get());
        }


    }


    @Test
    public void ceui_如果为null就设计默认值避免空指针() {
        Optional<Employee> op = Optional.ofNullable(null);
        Employee emp = op.orElse(new Employee("张三"));
        System.out.println(emp);

    }

    @Test
    public void ceui_没内容空指针异常() {
//        Optional<Employee> op = Optional.ofNullable(null);
//        System.out.println(op.get()); //没有内容依然是空指针异常
//
//        Optional<Employee> op = Optional.empty();
//        System.out.println(op.get()); //没有内容依然是空指针异常
    }

    /**
     * 创建Optional实例
     */
    @Test
    public void ceui_Optional创建实例() {

        Employee employee = new Employee();
        System.out.println("employee = " + employee);
        System.out.println("-------------");
        Optional<Employee> op = Optional.of(new Employee());
        Employee emp = op.get();
        System.out.println(emp);//获取内容和创建是一样的.

        Employee employee1 = null;
        //也会出现空指针异常
        Optional<Employee> employee11 = Optional.of(employee1);

    }

    @Test
    public void test5() {
        Man man = new Man();

        String name = getGodnessName(man);
        System.out.println(name);
    }

    //需求:获取一个男人心中女神的名字
    public String getGodnessName(Man man) {
        if (man != null) {
            Godness g = man.getGod();

            if (g != null) {
                return g.getName();
            }
        }

        return "张";
    }


}