java:java8新特性(Lambda 表達式、方法引用、構造器引用、數組引用、Stream API)

 

  • 速度更快

    • 對 HashMap 、ConcurrentHashMap低層的數據結構(數組+鏈表+二叉樹)

    • 低層的內存結構(將永久區更新爲元空間,元空間使用的是物理內存)

  • 代碼更少(增加了新的語法 Lambda 表達式)

  • 強大 Stream API

  • 便於並行

  • 最大化減少空指針異常 Optional

  • 關於時間日期的 API


目錄

一、Lambda 表達式

爲什麼使用 Lambda 表達式

Lambda 表達式的基礎語法

函數式接口

Java8內置四大核心函數式接口

其他接口

二、方法引用、構造器引用、數組引用

方法引用

構造器引用

數組引用

三、Stream API

Stream 操作的三個步驟:

創建 Stream

中間操作

終止操作


 

 

一、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——接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流

  • 終止操作

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章