Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | Github | OSChina 博客 | 云社区 | 云栖社区 | Facebook | Linkedin | 视频教程 | 打赏(Donations) | About
知乎专栏多维度架构 | 微信号 netkiller-ebook | QQ群:128659835 请注明“读者”

1.9. Optional

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

	
	

1.9.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);		
		
		

1.9.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());
		}
		
		

1.9.3. isPresent 如果值存在返回true,否则返回false。

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

1.9.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());
	});		
		
		

1.9.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		
		
		

1.9.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());
		
		
		

1.9.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"));		
		
		

1.9.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());
		}

	}

}
		
		

1.9.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"));		
		
		

1.9.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"));		
		
		

1.9.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);
			});
		});		
		
		

1.9.12. stream()

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

1.9.13. or()

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

1.9.14. example

		
		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());