探索Java8:(一)Stream的使用

Java 8 API添加了一個(gè)新的抽象稱為流Stream,可以讓你以一種聲明的方式處理數(shù)據(jù)。

Stream 使用一種類似用 SQL 語句從數(shù)據(jù)庫查詢數(shù)據(jù)的直觀方式來提供一種對 Java 集合運(yùn)算和表達(dá)的高階抽象。

Stream API可以極大提高Java程序員的生產(chǎn)力,讓程序員寫出高效率、干凈、簡潔的代碼。

這種風(fēng)格將要處理的元素集合看作一種流, 流在管道中傳輸, 并且可以在管道的節(jié)點(diǎn)上進(jìn)行處理, 比如篩選, 排序,聚合等。

元素流在管道中經(jīng)過中間操作(intermediate operation)的處理,最后由最終操作(terminal operation)得到前面處理的結(jié)果。


什么是 Stream?

Stream(流)是一個(gè)來自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作

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

和以前的Collection操作不同, Stream操作還有兩個(gè)基礎(chǔ)的特征:

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

一、流的創(chuàng)建

  • stream() ? 為集合創(chuàng)建串行流。
  • parallelStream() ? 為集合創(chuàng)建并行流。parallelStream其實(shí)就是一個(gè)并行執(zhí)行的流.它通過默認(rèn)的ForkJoinPool,可能提高你的多線程任務(wù)的速度。并行流在遍歷時(shí)可能是無序的。
public class ParallelStream {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        numbers.stream().forEach(System.out::print);  
    }
}

二、 forEach、map、filter、limit、sorted

numbers.stream().forEach(System.out::print);  
numbers.stream().forEach(i->System.out.print(i));  

上述兩種方法是等價(jià)的。

forEach

forEach用來對stream中的數(shù)據(jù)進(jìn)行迭代,比如上面創(chuàng)建流的操作就使用了forEach。看會上面的例子后理解forEach不會很難的。需要注意的是,forEach操作是不能改變遍歷對象本身的。

Map

map 方法用于映射每個(gè)元素到對應(yīng)的結(jié)果,多數(shù)情況下用來處理數(shù)據(jù)。下面給出一個(gè)讓原list個(gè)位置元素自增2的代碼:

public class MapDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> outPutList = numbers.stream().map(i -> i + 2).distinct().collect(Collectors.toList());
        outPutList.forEach(n->System.out.print(n+" "));
    }
}

filter

filter 方法用于通過設(shè)置的條件過濾出元素。以下代碼片段使用 filter 方法過濾出空字符串:

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

Limit

limit 方法用于獲取指定數(shù)量的流。 以下代碼片段使用 limit 方法打印出 10 條數(shù)據(jù):

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

還有一個(gè)常用的是配合skip()方法用來進(jìn)行分頁操作。

int pageSize=10;
int currentPage=1;
return pageList.stream()
        .skip(pageSize * (currentPage-1))
        .limit(pageSize)
        .collect(Collectors.toList());

sorted

sorted 方法用于對流進(jìn)行排序。以下代碼片段使用 sorted 方法對輸出的 10 個(gè)隨機(jī)數(shù)進(jìn)行排序:

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

Collectors

Collectors 可用于返回列表或字符串,上面介紹map的例子就用到了Collectors,下面給出菜鳥教程的一個(gè)例子:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("篩選列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

三、 統(tǒng)計(jì)

顧名思義,統(tǒng)計(jì)就是用來統(tǒng)計(jì)數(shù)據(jù)的,一般用于int、double、long等基本類型上。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("列表中最大的數(shù) : " + stats.getMax());
System.out.println("列表中最小的數(shù) : " + stats.getMin());
System.out.println("所有數(shù)之和 : " + stats.getSum());
System.out.println("平均數(shù) : " + stats.getAverage());

Stream先介紹到這里,我們Stream代碼覺得陌生是因?yàn)閯偨佑|聲明式編程的風(fēng)格,下一篇應(yīng)該會介紹lambda表達(dá)式和Optional的用法,我們會更多地用聲明式的編程風(fēng)格。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言: 講Stream之前,先來用個(gè)小需求帶入本文。畢竟代碼看的最清楚。 正文: 項(xiàng)目某個(gè)頁面有個(gè)需求,將關(guān)鍵詞和...
    T9的第三個(gè)三角閱讀 2,486評論 1 9
  • 了解Stream ? Java8中有兩個(gè)最為重要的改變,一個(gè)是Lambda表達(dá)式,另一個(gè)就是Stream AP...
    龍歷旗閱讀 3,445評論 3 4
  • Java SE 8中的主要新語言功能是lambda表達(dá)式。您可以將lambda表達(dá)式視為匿名方法;類似方法,lam...
    ATG丶MapleLeaf閱讀 1,123評論 0 1
  • 紅腫都是換膚的必經(jīng)之路
    橘貓飯閱讀 397評論 0 0
  • 本人資深桐華小說原著迷。在桐華的翻拍劇中,至今為止也就《步步驚心》讓人覺得是終于原著了,也算業(yè)界良心。大漢情緣三部...
    1f47d243c240閱讀 398評論 0 1

友情鏈接更多精彩內(nèi)容