目录
一、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);//false
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流的简单运用