1.避免空指針異常-Optional 類
空指針異常是我們日常項目中經常出現的問題,一般在操作前必須進行判空處理,Java8中引入了 Optional 類可以幫助我們避免顯式判空處理。
- Optional.of(T value),該方法通過一個非 null 的 value 來構造一個 Optional,返回的 Optional 包含了 value 這個值。對於該方法,傳入的參數一定不能爲 null,否則便會拋出 NullPointerException。
- Optional.ofNullable(T value),該方法和 of 方法的區別在於,傳入的參數可以爲 null
2.時間工具類-LocalDateTime
LocalDateTime是用於處理日期和時間的新API,比之前使用Date和Calendar更加方便。
// 取當前日期:
LocalDate today = LocalDate.now(); // -> 2014-12-24
// 根據年月日取日期:
LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25
// 根據字符串取:
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // 嚴格按照ISO yyyy-MM-dd驗證,02寫成2都不行,當然也有一個重載方法允許自己定義格式
LocalDate.parse("2014-02-29"); // 無效日期無法通過:DateTimeParseException: Invalid date
// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2017-03-01
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2017-03-02
// 取本月最後一天,再也不用計算是28,29,30還是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2017-12-31
// 取下一天:
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 變成了2018-01-01
// 取2017年1月第一個週一,用Calendar要死掉很多腦細胞:
LocalDate firstMondayOf2015 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2017-01-02
3.流式處理-Stream
Stream是 Java 8新增加的類,用來補充集合類。Stream代表數據流,流中的數據元素的數量可能是有限的,也可能是無限的。
Stream提供了提供了串行和並行兩種類型的流,保持一致的接口,提供函數式編程方式,以管道方式提供中間操作和最終執行操作,爲Java語言的集合提供了現代語言提供的類似的高階函數操作,簡化和提高了Java集合的功能。
參考鏈接 Stream流處理
4.lambda表達式
那麼在Java8之前,可以藉助匿名內部類來實現一個List<String>按字符串長度進行排序,使用Lambda表達式來實現可以只需要更簡單的代碼。
List<String> words = Arrays.asList("apple", "banana", "pear");
//java8之前的內部類方法
words.sort(new Comparator<String>() {
@Override
public int compare(String w1, String w2) {
return Integer.compare(w1.length(), w2.length());
}
});
//lambda表達式
words.sort((String w1, String w2) -> {
return Integer.compare(w1.length(), w2.length());
});
5.函數式接口
lambda表達式可以更好的完成函數式接口。創建包含單一抽象方法的接口,併爲其添加@FunctionalInterface註解,這類接口稱爲函數式接口。該註解不是必須的,通常需要加上,會觸發編譯器編譯時校驗接口是否符合要求,通常該接口只包含一個抽象方法,但是可以定義object的toString
和equals
方法。
/**
* 函數式接口
* @param <T>
*/
@FunctionalInterface
interface Checker<T extends String>{
boolean check(T t);
}
@FunctionalInterface
interface Out<T>{
void achievement(T t);
}
public class FunctionalInterfaceTest {
@Test
public void testLambda() {
List<String> demoList = Arrays.asList("小明", "Zing", "阿三", "小紅", "趙日天");
rollCall(demoList,
name-> name.startsWith("Z"),
name->{
String rate = name + "是單身狗!";
System.out.println(rate);
});
}
public void rollCall(List<? extends String> list, Checker checker,Out out){
for(String name : list){
if(checker.check(name)){
out.achievement(name);
}
}
}
}
6.方法引用
方法引用是一種語法糖,編譯器會將其轉換成函數式接口的實現對象,存在三種方法引用:引用方法、引用構造器、引用數組。這些方法主要是引用 java.util.function包中方法,可以參考JAVA 8 函數式接口( java.util.function 詳解)。
//引用方法
// Consumer<String> consumer = x -> System.out.println(x);
// println對應抽象方法的具體實現
Consumer<String> consumer = System.out::println;
consumer.accept("This is Major Tom");
// Function<Long, Long> f = x -> Math.abs(x);
// abs對應抽象方法的具體實現
Function<Long, Long> f = Math::abs;
System.out.println(f.apply(-3L));
// BiPredicate<String, String> b = (x,y) -> x.equals(y);
BiPredicate<String, String> b = String::equals;
System.out.println(b.test("abc", "abcd"));
//引用構造器
// Function<Integer, StringBuffer> fun = n -> new StringBuffer(n);
Function<Integer, StringBuffer> fun = StringBuffer::new;
StringBuffer buffer = fun.apply(10);
//引用數組
// Function<Integer, int[]> fun = n -> new int[n];
Function<Integer, int[]> fun = int[]::new;
int[] arr = fun.apply(10);