使用optional的好處:是一個可以包含或不可以包含非空值的容器對象,更加友好的處理程序中的空對象。
Optional<T>有方法 isPresent() 和 get() 是用來檢查其包含的對象是否為空或不是,然后返回它,如:
Optional<SomeType> someValue = someMethod();
if (someValue.isPresent()) { // check
someValue.get().someOtherMethod(); // retrieve and call
}
下面這個案例涉及到Lambda表達式 方法引用,是將單詞流中第一個以"L"開始單詞取出,作為返回結果是一個Optional<String>。
使用ifPresent()
這個案例的代碼如下:
Stream<string> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
Optional<string> longest = names
.filter(name -> name.startsWith("L"))
.findFirst();
longest.ifPresent(name -> {
String s = name.toUpperCase();
System.out.println("The longest name is "+ s);
});
這里ifPresent() 是將一個Lambda表達式作為輸入,T值如果不為空將傳入這個lambda。那么這個lambda將不為空的單詞轉為大寫輸出顯示。在前面names單詞流尋找結果中,有可能找不到開始字母為L的單詞,返回為空,也可能找到不為空,這兩種情況都傳入lambda中,無需我們打開盒子自己編寫代碼來判斷,它自動幫助我們完成了,無需人工干預。
使用map()
如果你想從Optional<T>中返回一個值怎么辦?使用 map(),如下:
Stream<string> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
Optional<string> longest = names
.filter(name -> name.startsWith("L"))
.findFirst();
Optional<string> lNameInCaps = longest.map(String::toUpperCase);
使用Optional<T>的map方法能夠返回另外一個Optional,如上面的 LnameInCaps,因為傳入map()的參數值也許會導致一個空值。
使用orElse()
如果在T可能空時你需要一個值的話,那么可以使用 orElse(),它能在T值存在的情況下返回這個值,否則返回輸入值。
Stream<String> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
Optional<String> longest = names
.filter(name -> name.startsWith("Q"))
.findFirst();
String alternate = longest.orElse("Nimrod");
System.out.println(alternate); //prints out "Nimrod"
使用orElseGet()
orElseGet() 方法類似於orElse(),但是不是直接返回輸入參數,而是調用輸入參數,返回調用的結果,這個輸入參數通常是lambda:
Stream<String> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
Optional<String> longest = names
.filter(name -> name.startsWith("Q"))
.findFirst();
String alternate = longest.orElseGet(() -> {
// perform some interesting code operation
// then return the alternate value.
return "Nimrod";
});
System.out.println(alternate);
使用 orElseThrow()
orElseThrow()是在當遭遇Null時,決定拋出哪個Exception時使用:
Stream<String> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
Optional<String> longest = names
.filter(name -> name.startsWith("Q"))
.findFirst();
longest.orElseThrow(NoSuchElementStartingWithQException::new);
第二部分:
在Java 8中stream().map(),您可以將對象轉換為其他對象。查看以下示例:
List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList());
Collectors 實現了接口 Collector<T,A,R>
T: 需要進行reduce操作的元素類型
A:reduce操作的動態集合類型
R:reduce操作的結果類型
舉例
//將名字集合到list
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
//將名字集合到TreeSet
Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
//將名字轉換為String,並連接為一個字符串
String joined = things.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
//計算員工的工資總額
int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));
//根據部門將員工分組:
Map<Department, List<Employee>> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
//計算不同部門的員工工資總額
Map<Department, Integer> totalByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
//划分及格和不及格的學生
Map<Boolean, List<Student>> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
Collectors的官方說明見:
官網文檔
如果你對Function接口不是很了解,那么在使用這些方法時會很容易出錯,下面進行簡單的介紹:
Function<T, R>
T—函數的輸入類型
R-函數的輸出類型
也就是通過這個函數,可以將一個類型轉換為另一個類型,比如下面的例子:
//定義一個function 輸入是String類型,輸出是 EventInfo 類型, EventInfo是一個類。
Function<String, EventInfo> times2 = fun -> { EventInfo a = new EventInfo(); a.setName(fun); return a;};
String[] testintStrings={"1","2","3","4"};
//將String 的Array轉換成map,調用times2函數進行轉換
Map<String,EventInfo> eventmap1=Stream.of(testintStrings).collect(Collectors.toMap(inputvalue->inputvalue, inputvalue->times2.apply(inputvalue)));
如果Collectors.toMap的轉換過程很簡單,比如輸入和輸出類型相同,則不需要另外定義Function,例如:
Map<String,String> eventmap2=Stream.of(testStrings).collect(Collectors.toMap(inputvalue->inputval
