Java8新特性之Stream流式編程----附API應用實例

一.Stream介紹

  • Java 8 API添加了一個新的抽象稱爲流Stream,可以讓你以一種聲明的方式處理數據
  • Stream 使用一種類似用 SQL 語句從數據庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象
  • Stream API可以極大提高Java程序員的生產力,讓程序員寫出高效率、乾淨、簡潔的代碼

這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。

元素流在管道中經過中間操作(intermediate operation)的處理,最後由最終操作(terminal operation)得到前面處理的結果

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

二.什麼是Stream

Stream(流)是一個來自數據源的元素隊列並支持聚合操作

  • 元素是特定類型的對象,形成一個隊列。 Java中的Stream並不會存儲元素,而是按需計算
  • 數據源:流的來源。 可以是集合,數組,I/O channel, 產生器generator 等
  • 聚合操作:類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted等

Stream操作還有兩個基礎的特徵:

  • Pipelining: 中間操作都會返回流對象本身。 這樣多個操作可以串聯成一個管道, 如同流式風格(fluent style)。 這樣做可以對操作進行優化, 比如延遲執行(laziness)和短路( short-circuiting)
  • 內部迭代: 以前對集合遍歷都是通過Iterator或者For-Each的方式, 顯式的在集合外部進行迭代, 這叫做外部迭代。 Stream提供了內部迭代的方式, 通過訪問者模式(Visitor)實現

三.Stream的操作步驟

在這裏插入圖片描述
Stream的使用需要經過三個步驟,創建,中間操作,結果


1.創建Stream

		//1.通過Collection接口的Stream()方法
 		List<String> list = Arrays.asList("1","2","3","4","0","222","33");
        Stream<String> stream = list.stream();
		Stream<String> stream1 = list.parallelStream();

		//2.通過Arrays中的靜態方法stream()獲取數組流
		IntStream stream = Arrays.stream(new int[]{1,2,3});

 		//3.通過Stream類中的 of()靜態方法獲取流
 		Stream<String> stream = Stream.of("a","b","c");


		//4.無限流
		//迭代(需要傳入一個種子,也就是起始值,然後傳入一個一元操作)
     	Stream<Integer> stream1 = Stream.iterate(2, (x) -> x * 2);

     	//生成(無限產生對象)
     	Stream<Double> stream2 = Stream.generate(() -> Math.random());



2.Stream的中間操作

多箇中間操作可以連接起來形成一個流水線,除非流水 線上觸發終止操作,否則中間操作不會執行任何的處理! 而在終止操作時一次性全部處理,稱爲惰性求值

一.篩選與切片
在這裏插入圖片描述

代碼示例:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 獲取空字符串的數量
long count = strings.stream().filter(string -> string.isEmpty()).count();

filter方法傳入一個Predicate,獲得空字符串數量

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

limit指定流的數量


二.映射

在這裏插入圖片描述

map 方法用於映射每個元素到對應的結果,以下代碼片段使用 map 輸出了元素對應的平方數:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 獲取對應的平方數
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

三.排序
在這裏插入圖片描述
sorted 方法用於對流進行排序。以下代碼片段使用 sorted 方法對輸出的 10 個隨機數進行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

3.Stream的終止操作

終止操作分爲三種,查找匹配,歸約,和收集

查找與匹配:檢查是否匹配某種斷言,或者返回某些元素
在這裏插入圖片描述

歸約
在這裏插入圖片描述
備註:map 和reduce 的連接通常稱爲map-reduce 模式,因Google 用它 來進行網絡搜索而出名

收集:這個很常用,就是把操作做完的元素收集到某個對象中

在這裏插入圖片描述


四.StreamAPI應用實例


	/*
	  	1.	給定一個數字列表,如何返回一個由每個數的平方構成的列表呢?
		,給定【1,2,3,4,5】, 應該返回【1,4,9,16,25】。
	 */
	@Test
	public void test1(){
		Integer[] nums = new Integer[]{1,2,3,4,5};
		
		Arrays.stream(nums)
			  .map((x) -> x * x)
			  .forEach(System.out::println);
	}

使用了Arrays類來構造stream,使用了map對每一個元素進行映射,最後使用forEach終止操作輸出。


/*
	 2.	怎樣用 map 和 reduce 方法數一數流中有多少個Employee呢?
	 */
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Status.BUSY),
			new Employee(101, "張三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	
	@Test
	public void test2(){
		Optional<Integer> count = emps.stream()
			.map((e) -> 1)
			.reduce(Integer::sum);
		
		System.out.println(count.get());
	}
發佈了74 篇原創文章 · 獲贊 4 · 訪問量 2485
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章