java Optional操作

一、Optional 对象的创建

1.使用 of 创建

		Student student = new Student("王五", 80);
        Optional<Student> optional = Optional.of(student);

2.使用 ofNullable 创建

		Student student = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student);

3.of 和 ofNullable 的区别

of 接收的值不能为 null,否则会报空指针异常:

		Student student = null;
		 //of 里只要传的参数只要是 null,就会报空指针异常
        Optional<Student> optional = Optional.of(student);

ofNullable 接收的值可以是 null,不会报空指针异常,但如果接收的值是是 null,在使用 get() 获取的时候就会报空指针:
( get() 方法是用于从 Optional 对象中获取值,在下面第四部分会介绍到)

		Student student = null;
		//ofNullable 接收的值可以为 null 
        Optional<Student> optional = Optional.ofNullable(student);
        //如果上面ofNullable 里接收的值 为 null ,下面使用 get() 获取对象会报空指针异常
        Student student1 = optional.get();

二、isPresent() 和 isEmpty() 判空处理

1.isPresent()

使用 isPresent 方法来判断非空,isPresent 相当于 !=null

		
		Student student1 = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student1);
		//将输出:student1不为空的操作
        if (optional.isPresent()){
            System.out.println("student1不为空的操作");
        }else {
            System.out.println("student1为空的操作");
        }
		
		
		Student student2 = null;
        Optional<Student> optional2 = Optional.ofNullable(student2);
		//将输出:student2为空的操作
        if (optional2.isPresent()){
            System.out.println("student2不为空的操作");
        }else {
            System.out.println("student2为空的操作");
        }

2.isEmpty()

从 Java 11 开始,我们可以使用 isEmpty 方法来处理相反的操作 isEmpty 相当于 ==null

		
		Student student1 = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student1);
        //将输出:student1不为空的操作
        if (optional.isEmpty()){
            System.out.println("student1为空的操作");
        }else {
            System.out.println("student1不为空的操作");
        }


        Student student2 = null;
        Optional<Student> optional2 = Optional.ofNullable(student2);
        //将输出:student2为空的操作
        if (optional2.isEmpty()){
            System.out.println("student2为空的操作");
        }else {
            System.out.println("student2不为空的操作");
        }

三、ifPresent() 和 ifPresentOrElse() 的条件动作

1.ifPresent()

ifPresent 相当于判断 !=null , 不为空才执行里面的代码:

		Student student1 = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student1);
        optional.ifPresent(name -> System.out.println("student1不为空,姓名为:"+name.getName()));

上面的代码和下面不使用 Optional 的代码效果是等效的:

		Student student1 = new Student("王五", 80);
        if (student1 != null){
            System.out.println("student1不为空,姓名为:"+student1.getName());
        }

2.ifPresentOrElse()

java 9里新增了 ifPresentOrElse(),当 Optional 里的值不为空则执行第一个参数里的代码,为空则执行第二个参数的代码,相当于 if-else :

        Student student = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student);
        optional.ifPresentOrElse( value -> System.out.println("student不为空,姓名:"+value.getName()), () -> System.out.println("student为空") );

四、使用 get 方法从 Optional 对象中获取值

使用 get 来获取值:

		Student student1 = new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student1);
        Student myStudent = optional.get();
        System.out.println("姓名:"+myStudent.getName());//输出姓名:王五

需要注意的是如果 student1 为 null,在使用 get() 获取值的时候会抛出 NoSuchElementException 异常:
(下面的写法只是样例,并不可取,后面会有几种代替 isPresent()和 get() )

		Student student1 = null;
        Optional<Student> optional = Optional.ofNullable(student1);
        Student myStudent = optional.get();
        System.out.println("姓名:"+myStudent.getName());
		Student student1 = null;
        Optional<Student> optional = Optional.ofNullable(student1);
        if (optional.isPresent()){
            Student myStudent = optional.get();
            System.out.println("姓名:"+myStudent.getName());
        }else {
            System.out.println("student1为空");
        }

五、orElse()与orElseGet()操作

orElse 与 orElseGet 可替代 get 操作并且可以避免 get 操作出现的 NoSuchElementException 异常

平常普通的代码:

		Student student1 = new Student("王五", 80);
        Student student2 = new Student("张三", 90);
        Student student3 = null;
        if (student1 != null) {
            student3 = student1;
        } else {
            student3 = student2;
        }

使用 orElse:

		Student student1 = new Student("王五", 80);
        Student student2 = new Student("张三", 90);
		Optional<Student> optional = Optional.ofNullable(student1);
		//先执行orElse里的语句,然后判断student1不为空则返回student1给 student3,否则返回student2给student3
        Student student3 = optional.orElse(student2);

使用 orElseGet:

		Student student1 = new Student("王五", 80);
        Student student2 = new Student("张三", 90);
		Optional<Student> optional = Optional.ofNullable(student1);
		//判断student1不为空则返回student1给 student3,否则返回student2给student3
        Student student3 = optional.orElseGet(()->student2);

orElse与orElseGet区别:
1.无论 Optional 中的值是否为空 orElse 中的代码都会执行,而 orElseGet 中的代码只有 Optional 中的值为空才会执行。
2.orElseGet 接收的是 Supplier<T> 类型的参数,而 orElse 接受的是T类型的参数;

当 student1 为空时 orElse 和 orElseGet 都会执行:

	public static void main(String[] args) throws Exception {
        Student student1 = null;
        Optional<Student> optional = Optional.ofNullable(student1);

        Student student2 = optional.orElse(getMyStudent());
        Student student3 = optional.orElseGet(() -> getMyStudent());
	}
		
	public static Student getMyStudent() {
        System.out.println("开始执行getMyStudent");
        return new Student("张三", 90);
    }

当 student1 不为空时只有 orElse 会执行:

	public static void main(String[] args) throws Exception {
        Student student1 =  new Student("王五", 80);
        Optional<Student> optional = Optional.ofNullable(student1);

        Student student2 = optional.orElse(getMyStudent());
        Student student3 = optional.orElseGet(() -> getMyStudent());
	}
		
	public static Student getMyStudent() {
        System.out.println("开始执行getMyStudent");
        return new Student("张三", 90);
    }

六、or()操作

Java 9引入了 or() 方法,or 操作与 orElse 和 orElseGet 操作相似,只不过 or 操作返回的是一个新的Optional 对象,而 orElse 和 orElseGet 操作返回的是 Optional 中的值

        String expected = null;
        Optional<String> value = Optional.ofNullable(expected);
        Optional<String> defaultValue = Optional.of("default");
        //or()方法将返回一个新的Optional对象
        Optional<String> result = value.or(() -> defaultValue);
        System.out.println(result.get());//default

七、filter()过滤操作

filter 将谓词作为参数并返回一个 Optional 对象

		Integer year = 2022;
        Optional<Integer> yearOptional = Optional.ofNullable(year);
        boolean is2022 = yearOptional.filter(y -> y == 2016).isPresent();
        System.out.println(is2022);//true
        boolean is2023 = yearOptional.filter(y -> y == 2017).isPresent();
        System.out.println(is2023);//false

八、map()转换值操作

map()方法:
map 将谓词作为参数并返回一个 Optional 对象

        List<String> companyNames = Arrays.asList("paypal", "oracle", "", "microsoft", "", "apple");
        Optional<List<String>> listOptional = Optional.of(companyNames);
        //获取companyNames的长度
        int size = listOptional.map(List::size).orElse(0);
        System.out.println(size);//6
        String password = " password ";
        Optional<String> passOpt = Optional.of(password);
        boolean correctPassword = passOpt.map(String::trim).filter(pass -> pass.equals("password")).isPresent();
        System.out.println(correctPassword);//true 

普通代码:

        Student student1 = new Student("aaa", 80);
        String stuName=null;
        if (student1!=null) {
            String name = student1.getName();
            if (name!=null) {
                stuName=name.toUpperCase();
            }
        }
        System.out.println(stuName);//AAA

使用 map() 代替上面的普通代码:

        Student student1 = new Student("aaa", 80);
        Optional<Student> optional = Optional.ofNullable(student1);
        String stuName=optional.map(u -> u.getName())
                .map(name -> name.toUpperCase())
                .orElse(null);
        System.out.println(stuName);

filter和map的联合使用:
Modem类

public class Modem {
    private Double price;

    public Modem(Double price) {
        this.price = price;
    }
    // 省略 getters 和 setters
}

普通的判断价格是否在在10到15之间的写法:

public boolean priceIsInRange1(Modem modem) {
    boolean isInRange = false;
    if (modem != null && modem.getPrice() != null && (modem.getPrice() >= 10 && modem.getPrice() <= 15)) {
        isInRange = true;
    }
    return isInRange;
}

而采用filter和map可以这么写:

public boolean priceIsInRange1(Modem modem) {
    return Optional.ofNullable(modem2)
       .map(Modem::getPrice)
       .filter(p -> p >= 10)
       .filter(p -> p <= 15)
       .isPresent();
}

九、flatMap()解包操作

flatMap() 方法作为转换值的替代方法。不同之处在于 map 仅在它们被解包时才转换值,而 flatMap 接受一个被包装的值并在转换之前解包它。
Person 类:

public class Person {
    private String name;
    private int age;
    private String password;

    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }

    public Optional<Integer> getAge() {
        return Optional.ofNullable(age);
    }

    public Optional<String> getPassword() {
        return Optional.ofNullable(password);
    }

    // 省略 getters 和 setters
}
    Person person = new Person("john", 26);
    Optional<Person> personOptional = Optional.of(person);

    Optional<Optional<String>> nameOptionalWrapper  =  personOptional.map(Person::getName);
    Optional<String> nameOptional  = nameOptionalWrapper.orElseThrow(IllegalArgumentException::new);
    String name1 = nameOptional.orElse("");
    System.out.println("john".equals(name1));

    String name = personOptional
      .flatMap(Person::getName)
      .orElse("");
	  System.out.println("john".equals(name));
}

十、stream ()方法

在 Java 9中添加到 Optional 类的最后一个方法是 stream() 方法,允许我们将 Optional 实例视为Stream

        Optional<List<String>> value = Optional.of(Arrays.asList("aaaa","bbbb","ccc"));
        List<String> collect = value.stream()
			.flatMap(Collection::stream)
			.filter(v->v.length()==4)
			.map(String::toUpperCase)
			.collect(Collectors.toList());
        System.out.println(collect);//[AAAA, BBBB]
}

参考:
Guide To Java 8 Optional
Java | Optional的12种实践建议
java1.8的Optional和Stream流的简单运用

Java OptionalJava 8 引入的一个类,用于解决经常出现的空指针异常。它的设计初衷是希望提供一种简洁的方式来处理可能为空的对象。 然而,Optional 也存在一些错误的用法,下面列举了一些常见的错误用法: 1. 非必要地使用 Optional:有些开发者过度使用 Optional,把所有的对象都包装成 Optional,这样会导致代码变得复杂且难以理解。只有当对象确实可能为空时,才应考虑使用 Optional。 2. 错误的使用 ifPresent 方法:ifPresent 方法用于判断 Optional 对象是否有值,如果有值则执行指定的方法。有些开发者错误地使用 ifPresent 方法来执行一些复杂的逻辑,这样会导致代码变得混乱。正确的做法是使用 map 或 flatMap 方法来进行链式操作。 3. 对空值的处理不当:如果没有正确处理 Optional 对象为空的情况,仍然会导致空指针异常的发生。应该使用 isPresent 方法或者使用 orElseThrow 方法来处理空值的情况。 4. 对 Optional 对象的滥用:有些开发者滥用 Optional 对象,把 Optional 当作方法的返回类型,这样会增加方法的复杂性,并且会误导调用者。正确的做法是根据具体情况判断是否需要使用 Optional。 总结来说,Java Optional 是一种处理可能为空对象的有效方式,但是需要注意一些错误的用法。我们应该根据具体情况,合理使用 Optional,并且避免过度使用 Optional,以及注意处理空值的情况。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值