-
速度更快
-
對 HashMap 、ConcurrentHashMap低層的數據結構(數組+鏈表+二叉樹)
-
低層的內存結構(將永久區更新爲元空間,元空間使用的是物理內存)
-
-
代碼更少(增加了新的語法 Lambda 表達式)
-
強大 Stream API
-
便於並行
-
最大化減少空指針異常 Optional
-
關於時間日期的 API
目錄
一、Lambda 表達式
爲什麼使用 Lambda 表達式
//原來將匿名內部類作爲參數進行傳遞
@Test
public void test1(){
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
}
//java8中的 Lambda 表達式
@Test
public void test2(){
TreeSet<String> ts = new TreeSet<>((x, y) -> x.compareTo(y));
}
代碼簡潔。方便,快速的完成了接口實例和內部類的功能。
Lambda 表達式的基礎語法
Lambda 提供了一個全新的操作符,該操作符爲“ -> ”, 該操作符稱爲箭頭操作或Lambda操作符。
箭頭操作符將 Lambda 表達式分爲兩部分:
左側:對應函數式接口中抽象方法的參數列表
右側:對函數式接口中抽象方法的實現,即 Lambda 體
- 語法格式一:無參,無返回值
Runnable r1 = () -> System.out.println("Hello Lambda!");
- 語法格式二:有一個參數,無返回值
Cusumer<String> cus = (x) -> System.out.println(x);
- 語法格式三:若Lambda表達式左側只有一個參數
Cusumer<String> cus = x -> System.out.println(x);
- 語法格式四:有兩個以上參數,Lambda體中有多個條語句,有返回值
Comparator<Integer> com = (x, y) -> {
System.out.println("Lambda體中多條語句");
return Integer.compare(x, y);
};
- 語法格式五:若 Lambda 體中只有一條語句,return 和 大括號可以省略不寫
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
- 語法格式六:Lambda 左側參數列表可以省略不寫,因爲 Java 編譯器可以通過上下文推斷出數據類型,即“類型推斷”
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
注意:Lambda 表達式需要函數式接口的支持
函數式接口
若一個接口中只有一個抽象方法,該接口爲函數式接口。可以使用 @FunctionalInterface 修飾,說明該接口必須是函數式接口
@FunctionalInterface
public interface MyFunction<T>{
T apply(T t);
}
Java8內置四大核心函數式接口
函數式接口 |
參數類型 |
返回類型 |
用途 |
Consumer<T> 消費型接口 |
T |
void |
對類型爲T的對象應用操作,包含方法: void accept(T t) |
Supplier<T> 供給型接口 |
無 |
T |
返回類型爲T的對象,包含方法:T get(); |
Function<T, R> 函數型接口 |
T |
R |
對類型爲T的對象應用操作,並返回結果。結果是R類型的對象。包含方法:R apply(T t); |
Predicate<T> 斷定型接口 |
T |
boolean |
確定類型爲T的對象是否滿足某約束,並返回 boolean 值。包含方法 boolean test(T t); |
其他接口
函數式接口 |
參數類型 |
返回類型 |
用途 |
BiFunction<T, U, R> |
T, U |
R |
對類型爲 T, U 參數應用操作,返回 R 類型的結果。包含方法爲 R apply(T t, U u); |
UnaryOperator<T> (Function子接口) |
T |
T |
對類型爲T的對象進行一元運算,並返回T類型的結果。包含方法爲 T apply(T t); |
BinaryOperator<T> (BiFunction 子接口) |
T, T |
T |
對類型爲T的對象進行二元運算,並返回T類型的結果。包含方法爲 T apply(T t1, T t2); |
BiConsumer<T, U> |
T, U |
void |
對類型爲T, U 參數應用操作。包含方法爲 void accept(T t, U u) |
ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T> |
T |
int long double |
分別計算int、long、double、值的函數 |
IntFunction<R> LongFunction<R> DoubleFunction<R> |
int long double |
R |
參數分別爲int、long、double 類型的函數 |
二、方法引用、構造器引用、數組引用
方法引用
若 Lambda 體中需要完成的功能,已經有現成的方法,提供了實現,可以選擇使用方法引用替代Lambda表達式。(方法引用是 Lambda 表達式的另外一種表現形式)
格式:
對象::實例方法名
Consumer<String> con = (x) -> System.out.println(x);
Consumer<String> con2 = System.out::println;
注意:接口中抽象方法的參數列表必須與Lambda體中調用方法的參數列表保持一致!
類::靜態方法名
Compartor<Integer> com = Integer::compare;
類::實例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
BiPredicate<String, String> bp2 = String::equals;
注意:若Lambda參數列表中第一個參數,是 Lambda體中方法的調用者,第二個參數是Lambda體中方法的參數
構造器引用
格式: ClassName::new
與函數式接口相結合,自動與函數式接口中方法兼容。
可以把構造器引用賦值給定義的方法,與構造器參數列表要與接口中抽象方法的參數列表一致!
數組引用
格式: type[ ] :: new
三、Stream API
Java8中有兩大最爲重要的改變。第一個是 Lambda 表達式;另外一個則是 Stream API(java.util.stream.*)。
Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查找、過濾和映射數據等操作。 使用Stream API 對集合數據進行操作,就類似於使用 SQL 執行的數據庫查詢。也可以使用 Stream API 來並行執行操作。簡而言之,Stream API 提供了一種高效且易於使用的處理數據的方式。
Stream 操作的三個步驟:
-
創建 Stream
//1. 創建 Stream 的四種方式
@Test
public void test1(){
//1. 通過 Collection 系列集合提供兩個 stream() 和 parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
//2. 通過 Arrays 中的 stream() 獲取一個數組流
Integer[] nums = new Integer[10];
Stream<Integer> stream2 = Arrays.stream(nums);
//3. 通過 Stream 類中靜態方法 of
Stream stream3 = Stream.of("aaa", "bb", "cc");
//4. 創建無限流
//迭代
/*Stream stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.forEach(System.out::println);*/
//生成
Stream stream5 = Stream.generate(Math::random).limit(2);
stream5.forEach(System.out::println);
}
-
中間操作
中間操作流不會進行任何操作,只有做了終止操作後,流一次性的執行全部,“惰性求值”
篩選與切片 filter——接收 Lambda , 從流中排除某些元素。 limit——截斷流,使其元素不超過給定數量。 skip(n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補 distinct——篩選,通過流所生成元素的 hashCode() 和 equals() 去除重複元素
映射 map——接收 Lambda , 將元素轉換成其他形式或提取信息。接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。 flatMap——接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流
-
終止操作