Optional

package cn.anzhongwei.lean.demo.optional;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Optional;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
    private Address address;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Optional<String> optionalGetName() {
        return Optional.ofNullable(this.name);
    }
}
package cn.anzhongwei.lean.demo.optional;

import lombok.Data;

@Data
public class Address {
    private String city;
    private String addInfo;
}
package cn.anzhongwei.lean.demo.optional;

import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

public class OptionalTest {

    /**
     * Optional(T value),empty(),of(T value),ofNullable(T value)
     * Optional(T value) 是private的属于内部方法
     */
    @Test
    public void test1() {
        //of(T value) 是实际上调用了Optional(T value) 而其内部的requireNonNull方法源码中判断value==null时会抛出空指针异常
        //在开发中如果不想隐藏空指针异常时 使用of函数, 不过这种情况几乎不用
        //Optional<Person> p1 = Optional.of(null);

        //所以如果要创建一个value为null的Optional对象则应该使用 empty()
        Optional<Person> pnull = Optional.empty();
        //而ofNullable(T value) 则是一个三元表达式  return value == null ? empty() : of(value);
        Optional<Person> p0 = Optional.ofNullable(null);
        Optional<Person> p1 = Optional.ofNullable(new Person("zhangs", 20));
    }

    /**
     * orElse(T other),orElseGet(Supplier other)和orElseThrow(Supplier exceptionSupplier)
     * 这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。
     * orElse 和 orElseGet 没区别 可以认为时完全一样的代码
     *
     * orElseThrow 则会当value为空时抛出一个自定义异常
     */
    @Test
    public void test2() {
        Person p = null;
        //当p值不为null时,orElse函数依然会执行createUser()方法
        p = Optional.ofNullable(p).orElse(new Person("zhangsan", 20));
        System.out.println("调用orElse 当p为null时:"+p);
        //而当p不为空,则相当于使用get()方法
        p = Optional.ofNullable(p).orElse(new Person("王五", 60));
        System.out.println("调用orElse 此时p不为null时:"+p);
        //
        p = null;
        //重新赋值p=null
        System.out.println("重新赋值p=:"+p);
        p = Optional.ofNullable(p).orElseGet(() -> new Person("lisi", 30));
        System.out.println("orElseGet 当p为null时:"+p);
        p = Optional.ofNullable(p).orElseGet(() -> new Person("zhaoliu", 34));
        System.out.println("orElseGet 此时p不为null时:"+p);


    }
    @Test
    public void testOrElseThrow() {
        Person p = new Person("lisi", 30);
        p = Optional.ofNullable(p).orElseThrow(()-> new RuntimeException("用户不存在"));
        System.out.println("orElseThrow 此时p不为null时:"+p);
        p = null;
        p = Optional.ofNullable(p).orElseThrow(()-> new RuntimeException("用户不存在"));
    }

    /**
     * map(Function mapper)和flatMap(Function> mapper)
     * 这两个函数做的是转换值的操作
     */
    @Test
    public void test3() {
        Person p = new Person("lisi", 30);
        String name = Optional.ofNullable(p).map( person -> person.getName()).get();
        System.out.println("name="+name);

        String optionalName = Optional.ofNullable(p).flatMap(person -> person.optionalGetName()).get();
        System.out.println("optionalName="+optionalName);
    }

    /**
     * isPresent()和ifPresent(Consumer consumer)
     * isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。
     */
    @Test
    public void test4() {
        Person p = null;
        Optional.ofNullable(p).ifPresent(person -> {

        });
    }

    /**
     * filter(Predicate predicate)
     */
    @Test
    public void test5() {
        Person p = null;
        //如果 p.name 长度小于6则返回, 否则返回EMPTY
        Optional<Person> p1 = Optional.ofNullable(p).filter(u -> u.getName().length()<6);
    }

    /**
     * 实战写法1
     */
    public String getCity(Person person)  throws Exception{
        if(person!=null){
            if(person.getAddress()!=null){
                Address address = person.getAddress();
                if(address.getCity()!=null){
                    return address.getCity();
                }
            }
        }
        throw new RuntimeException("取值错误");
    }
    public String getCity2(Person person) throws Exception{
        return Optional.ofNullable(person)
                .map(u-> u.getAddress())
                .map(a->a.getCity())
                .orElseThrow(()->new Exception("取值错误"));
    }

    /**
     * 实战写法2
     */
    public void dosomething(Person person) {
        if (Objects.nonNull(person)) {
            //......
        }
        Optional.ofNullable(person).ifPresent(person1 -> {
            //......
        });
    }

    /**
     * 实战写法3
     */
    public Person getUser1(Person user){
        if(user!=null){
            String name = user.getName();
            if(!"zhangsan".equals(name)){
                user = new Person();
                user.setName("zhangsan");
            }
        }else{
            user = new Person();
            user.setName("zhangsan");
        }
        return user;
    }
    public Person getUser2(Person user) {
        return Optional.ofNullable(user)
                .filter(u->"zhangsan".equals(u.getName()))
                .orElseGet(()-> {
                    Person user1 = new Person();
                    user1.setName("zhangsan");
                    return user1;
                });
    }



    public Person getUser3(Person user){
        if(user!=null){
            String name = user.getName();
            if(!"zhangsan".equals(name)){
                user.setName("zhangsan");
            }
        }else{
            user = new Person();
            user.setName("zhangsan");
        }
        return user;
    }
    public Person getUser4(Person user) {
        //这个逻辑一般来说不会这么写, 大多数情况下都是不为空且不为zhangsan时, 将name赋值成zhangsan,而不是重新实例化
        return Optional.ofNullable(user)
                .filter(u->"zhangsan".equals(u.getName()))
                .orElseGet(()-> {
                    if (Objects.nonNull(user)) {
                        user.setName("zhangsan");
                        return user;
                    } else {
                        Person user1 = new Person();
                        user1.setName("zhangsan");
                        return user1;
                    }


                });
    }
    @Test
    public void test6() {
        //getUser1 和 getUser2 只要name不等于 zhangsan, 就重新初始化
        Person p = new Person("wangwu", 26);
        Person p1 = getUser1(p);
        System.out.println("p1:"+p1);

        p = new Person("lisi", 23);
        Person p2 = getUser2(p);
        System.out.println("p2:"+p2);

        //getUser3 和 getUser4 name不等于 zhangsan, 只改变name=张三, 其他内容不变
        p = new Person("zhaosi", 26);
        Person p3 = getUser3(p);
        System.out.println("p3:"+p3);

        p = new Person("liuqi", 26);
        Person p4 = getUser4(p);
        System.out.println("p4:"+p4);
    }


    @Test
    public  void test7() {
        List<Person> personList = new ArrayList<>();
        Person p1 = new Person("zhangsan", 22);personList.add(p1);
        Person p2 = new Person("zhaosi", 29);personList.add(p2);
        Person p3 = new Person("wangwu", 22);personList.add(p3);
        Person p4 = new Person("lisen", 35);personList.add(p4);
        Person p5 = new Person("liuming", 248);personList.add(p5);

        Optional<Person> personOptional = personList.stream().filter(p -> p.getAge() > 22).findFirst();
        Person pp1 = personOptional.orElseGet(() -> personList.get(0));
        System.out.println(pp1);
        Person pp2 = personOptional.orElse(null);
        System.out.println(pp2);

        List<Person> personList2 = Optional.ofNullable(personList).orElseGet(ArrayList::new);
        System.out.println(personList2);

        Map<String, List<Person>> pMap = new HashMap<>();
//        List<Person> personList3 = Optional.ofNullable(pMap.get("随便写"))
//                //这种写法主要为了后面stream()的流式处理方式不会有空指针
//                //这样会空指针
//                .get()
//                .stream().collect(Collectors.toList());
//        System.out.println(personList3);

        List<Person> personList4 = Optional.ofNullable(pMap.get("随便写"))
                //这种写法主要为了后面stream()的流式处理方式不会有空指针
                .orElseGet(ArrayList::new)
                .stream().collect(Collectors.toList());
        System.out.println(personList4);
    }


}