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