Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

8.11. Optional

	
Optional.of("javastack").orElseThrow(); // javastack
 // 1

	
		

8.11.1. of() 为非null的值创建一个Optional。

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

		
		Optional<String> name = Optional.of("netkiller");
		if (name.isPresent()) {
			// 在Optional实例内调用get()返回已存在的值
			System.out.println(name.get());// 输出 netkiller
		}		
		
			

传入参数为null,抛出NullPointerException.

		
Optional<String> someNull = Optional.of(null);		
		
			

8.11.2. ofNullable() 为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

		
		Optional<String> name = Optional.ofNullable("netkiller");
		if (name.isPresent()) {
			// 在Optional实例内调用get()返回已存在的值
			System.out.println(name.get());// 输出 netkiller
		}

		Optional<String> empty = Optional.ofNullable(null);
		if (empty.isPresent()) {
			System.out.println(empty.get());
		}
		
			

8.11.3. isPresent 如果值存在返回true,否则返回false。ifEmpty() null 返回 true 否则返回 false

		
	//isPresent方法用来检查Optional实例中是否包含值
	if (name.isPresent()) {
		System.out.println(name.get());
	}
		
			

ifEmpty() 与 ifPresent() 刚好相反

8.11.4. ifPresent() 如果Optional实例有值执行 lambda 表达式

如果Optional实例有值,调用ifPresent()可以接受接口段或lambda表达式。类似下面的代码:

		
	Optional<String> name = Optional.ofNullable("netkiller");

	name.ifPresent((value) -> {
		System.out.println("hello " + value);
	});

	name.ifPresent((value) -> {
		System.out.println(value.length());
	});		
		
			

8.11.5. get() 返回值

如果Optional有值则将其返回,否则抛出NoSuchElementException。

		
		Optional<String> name = Optional.ofNullable("netkiller");
		System.out.println(name.get());
		
		Optional<String> empty = Optional.ofNullable(null);
		try {
			System.out.println(empty.get());
		} catch (NoSuchElementException e) {
			System.out.println(e.getMessage());
		}		
		
			

输出内容

		
netkiller
No value present		
		
			

8.11.6. orElse 如果有值则将其返回,否则返回指定的其它值。

如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。示例如下:

		
package cn.netkiller.test;

import java.util.Optional;

public class OptionalTest {

	public OptionalTest() {
		// TODO Auto-generated constructor stub
	}


	public static void main(String[] args) {

		Optional<String> name = Optional.ofNullable("netkiller");

		Optional<String> empty = Optional.ofNullable(null);

		System.out.println(name.orElse("There is some value!"));
		System.out.println(empty.orElse("There is no value present!"));

	}

}
		
			

输出

		
netkiller
There is no value present!		
		
			

指定默认值

		
	User user = new User();
	user.setId(1);
	user.setUsername("Neo");
	
	Optional<User> user = Optional.ofNullable(user).orElse(new User(0, "Unknown"));

	System.out.println("Username is: " + user.getUsername());
		
		
			

8.11.7. orElseGet与orElse方法类似,区别在于得到的默认值从 Supplier 返回。

orElseGet方法可以接受Supplier接口的实现用来生成默认值。示例如下:

		
package cn.netkiller.test;

import java.util.Optional;

public class OptionalTest {

	public OptionalTest() {
		// TODO Auto-generated constructor stub
	}


	public static void main(String[] args) {

		Optional<String> name = Optional.ofNullable("netkiller");

		Optional<String> empty = Optional.ofNullable(null);

		System.out.println(name.orElseGet(() -> "There is some value!"));
		System.out.println(empty.orElseGet(() -> "There is no value present!"));

	}

}		
		
			

		
Optional<User> user = Optional.ofNullable(user).orElseGet(() -> new User(0, "Unknown"));		
		
			

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

		
Optional<User> user = Optional
        .ofNullable(user)
        .orElseThrow(() -> new EntityNotFoundException("id=" + id + " 的用户没有找到"));
		
			

使用场景举例

		
@RequestMapping("/user/{id}")
public User getUser(@PathVariable Integer id) {
    Optional<User> user = userService.getUserById(id);
    return user.orElseThrow(() -> new EntityNotFoundException("id=" + id + " 的用户不存在"));
}

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> handleException(EntityNotFoundException ex) {
    return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}		
		
			
		
package cn.netkiller.test;

import java.util.Optional;

public class OptionalTest {

	public OptionalTest() {
		// TODO Auto-generated constructor stub
	}

	public static class ValueAbsentException extends Throwable {

		private static final long serialVersionUID = -1758502952187236809L;

		public ValueAbsentException() {
			super();
		}

		public ValueAbsentException(String msg) {
			super(msg);
		}

		@Override
		public String getMessage() {
			return "No value present in the Optional instance";
		}
	}

	public static void main(String[] args) {

		Optional<String> empty = Optional.ofNullable(null);

		try {
			// orElseThrow会抛出lambda表达式或方法生成的异常
			empty.orElseThrow(ValueAbsentException::new);
		} catch (Throwable ex) {
			// 输出 No value present in the Optional instance
			System.out.println(ex.getMessage());
		}

	}

}
		
			

8.11.9. map() 方法用来对Optional实例的值执行一系列操作

map方法用来对Optional实例的值执行一系列操作。通过一组实现了Function接口的lambda表达式传入操作。map方法示例如下:

		
	Optional<String> name = Optional.ofNullable("netkiller");
	Optional<String> upperName = name.map((value) -> value.toUpperCase());
	System.out.println(upperName.orElse("No value found"));		
		
			

		
		Optional<String> username = Optional.ofNullable("netKiller-Neo")
				.map((value) -> value.toLowerCase())
				.map((value) -> value.replace("n", "N"))
				.map(value -> value.replace('-', '_'));

		System.out.println("Username is: " + username.orElse("Unknown"));		
		
			

8.11.10. flatMap()

与 map() 区别在于flatMap中的mapper返回值必须是Optional

		
		Optional<String> username = Optional.ofNullable("netKiller-Neo").flatMap((value) -> Optional.of(value.toUpperCase()));

		System.out.println("Username is: " + username.orElse("No value found"));		
		
			

8.11.11. filter() 通过传入限定条件过滤Optional值

		
package cn.netkiller.test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

	public OptionalTest() {
		// TODO Auto-generated constructor stub
	}

	public static void main(String[] args) {

		for (String item : List.of("Neo", "Jerry", "Netkiller")) {
			Optional<String> username = Optional.of(item).filter((value) -> value.length() > 6);
			System.out.println("name is: " + username.orElse("The name is less than 6 characters"));
		}
	}

}
		
		
			

使用多个 filter 组合过滤数据

		
		List.of("Neo", "Jerry", "Netkiller", "Tom", "Anni", "Lisa", "Leo").forEach(item -> {
			Optional.of(item).filter((value) -> value.length() > 2).filter((value) -> value.contains("o")).ifPresent((n) -> {
				System.out.println(n);
			});
		});		
		
			

8.11.12. stream()

		
Optional.of("javastack").stream().count();		
		
			

8.11.13. or()

		
	String string = (String) Optional.ofNullable(null).or(() -> Optional.of("netkiller")).get();
	System.out.println(string);		
		
			

8.11.14. example

8.11.14.1. Optional 与 Map

				
		Optional<Map<String, Object>> name = Optional.of(new HashMap<String, Object>() {
			{
				put("id", 1);
				put("name", "Neo");
				put("age", 30);
			}
		});

		System.out.println(name.toString());
		name.map((m) -> m.put("count", 1));
		System.out.println(name.get());
		name.map((m) -> m.put("nickname", "netkiller"));
		name.map((m) -> m.remove("id"));
		System.out.println(name.get());
		Optional<Map<String, Object>> tmp = name.filter((m) -> ((Integer) m.get("age")) == 30);
		System.out.println("filter: " + tmp.get());		
				
				

8.11.14.2. 判断 Object 是否为 null

				
package cn.netkiller.utils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serial;
import java.io.Serializable;
import java.util.Optional;

@Data
@Slf4j
public class ResponseJson implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    private final boolean status; // 状态代码
    private final Code code; // 业务响应码
    private final Object data; // 返回业务参数
    private String reason = ""; // 返回信息描述

    public ResponseJson(boolean status, Code code, String reason, Object data) {
        this.status = status;
        this.code = code;
        this.reason = reason;
        this.data = data;
    }

    public ResponseJson(Object data) {
        Optional<Object> optional = Optional.ofNullable(data);
//        log.info(String.valueOf(optional.isEmpty()));
//        log.info(String.valueOf(optional.isPresent()));
//        log.info(String.valueOf(optional.get()));
        if (optional.isEmpty()) {
            this.status = false;
            this.code = Code.FAIL;
            this.reason = "失败";
            this.data = null;
        } else {
            this.status = true;
            this.code = Code.SUCCESS;
            this.reason = "成功";
            this.data = data;
        }
    }

    public enum Code {
        SUCCESS, // 业务处理成功
        COMPLIANCE, NONCOMPLIANT, ILLEGAL, FAIL // 业务处理失败

    }
}