1. 程式人生 > >Java流(Stream)操作例項-篩選、對映、查詢匹配

Java流(Stream)操作例項-篩選、對映、查詢匹配

準備工作

構建一個測試類,通過測試類先初始化一個數據源,具體如下。

public class TestObject {
    private String name;
    private String sex;
    private int age;
    private String email;
    private boolean isMng;

    public TestObject() {
    }

    public TestObject(String name,String sex,int age,String email,boolean isMng){
        this
.name=name; this.sex=sex; this.age=age; this.email=email; this.isMng=isMng; } //... ...get、set方法就不貼出來了,多又麻煩 }

在測試類中定義初始化資料來源

public class StreamOperation {
    static List<TestObject> list = Arrays.asList(
            new TestObject("Ron","M",10,"[email protected]
"
,false), new TestObject("KDS","W",10,"[email protected]",false), new TestObject("BoDuo","W",30,"[email protected]",false), new TestObject("CangJin","W",10,"[email protected]",false), new TestObject("XiaoZe","W",30,"[email protected]",true), new
TestObject("James","M",10,"[email protected]",true), new TestObject("Allen","M",50,"[email protected]",true), new TestObject("Smith","M",10,"[email protected]",true), new TestObject("Wade","M",20,"[email protected]",true), new TestObject("Wade","M",20,"[email protected]",false) ); //... ...流操作 }

用謂詞篩選

Streams介面支援filter方法,該操作會接受一個謂詞(一個返回boolean的函式)作為引數,並返回一個包括所有符合謂詞的元素的流。比如我們需要篩選isLeader為ture的資料並列印名字就可以按照如下的方式處理。

/**
     * @Comment 獲取Leader
     * @Author Ron
     * @Date 2017年11月24日 下午2:01:16
     * @return
     */
    public static List<TestObject> getLeader() {
        return list.stream().filter(TestObject::isLeader).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        List<TestObject> leaders = getLeader();
        leaders.stream().forEach(leader->System.out.println(leader.getName()));
    }

篩選各異的元素

流還支援一個叫作distinct的方法,它會返回一個元素各異(根據流所生成元素的hashCode和equals方法實現)的流。例如,以下程式碼會篩選出列表中所有的偶數,並確保沒有重複。

public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);
    }

截短流

流支援limit(n)方法,該方法會返回一個不超過給定長度的流。所需的長度作為引數傳遞給limit。如果流是有序的,則最多會返回前n個元素。比如選出前5個sex為M的物件並列印其名稱可以按如下的程式碼操作。

list.stream().filter(u->u.getSex().equals("M")).limit(5).forEach(u->System.out.println(u.getName()));

如果我們需要選出前5個sex為M的物件並按照名稱排序之後列印其名稱可以按如下的程式碼操作。

list.stream()
        .filter(u->u.getSex().equals("M"))
        .limit(5)
        .sorted(Comparator.comparing(TestObject::getName))
        .forEach(u->System.out.println(u.getName()));

跳過元素

流還支援skip(n)方法,返回一個扔掉了前n個元素的流。如果流中元素不足n個,則返回一個空流。請注意, limit(n)和skip(n)是互補的。例如,下面的程式碼將會跳過篩選出來的第一個元素並列印名字。

list.stream()
        .filter(u->u.getSex().equals("M"))
        .sorted(Comparator.comparing(TestObject::getName))
        .skip(1)
        .forEach(u->System.out.println(u.getName()));

對流中每一個元素應用函式

流支援map方法,它會接受一個函式作為引數。這個函式會被應用到每個元素上,並將其對映成一個新的元素(使用對映一詞,是因為它和轉換類似,但其中的細微差別在於它是“建立一個新版本”而不是去“修改”)。例如,下面的程式碼把方法引用TestObject::getName傳給了map方法,來提取流中使用者的名稱並列印:

list.stream()
.map(TestObject::getName)
.collect(Collectors.toList())
.forEach(System.out::println);

因為getName方法返回一個String,所以map方法輸出的流的型別就是Stream⁢String>。

我們來再看一個例子,我們把方法引用TestObject::getName傳給了map方法,來提取流中使用者的名稱,然後再列印使用者名稱稱的長度。你可以像下面這樣,給map傳遞一個方法引用String::length來解決這個問題:

list.stream()
        .map(TestObject::getName)
        .map(String::length)
        .collect(Collectors.toList())
        .forEach(System.out::println);

檢查謂詞是否至少匹配一個元素

anyMatch方法可以回答“流中是否有一個元素能匹配給定的謂詞”。比如,你可以用它來看看使用者列表裡面是否有名稱為Ron的物件可選擇:

if(list.stream().anyMatch(u->u.getName().equals("Ron"))){
        System.out.println("Ron已經到了");
    }

anyMatch方法返回一個boolean,因此是一個終端操作。

檢查謂詞是否匹配所有元素

allMatch方法的工作原理和anyMatch類似,但它會看看流中的元素是否都能匹配給定的謂詞。比如,你可以用它來看看使用者是否都大於10歲。

if(list.stream().allMatch(u->u.getAge()>=10)){
        System.out.println("很棒,都大於10歲");
    }else{
        System.out.println("原來都還沒發育");
    }

和allMatch相對的是noneMatch。它可以確保流中沒有任何元素與給定的謂詞匹配。比如,你可以用noneMatch重寫前面的例子:

if(list.stream().noneMatch(u->u.getAge()<10)){
        System.out.println("很棒,都大於10歲");
    }else{
        System.out.println("原來都還沒發育");
    }

anyMatch、 allMatch和noneMatch這三個操作都用到了我們所謂的短路,這就是大家熟悉的Java中&&和||運算子短路在流中的版本。

Optional簡介

Optional<T>類(java.util.Optional)是一個容器類,代表一個值存在或不存在。Java 8的庫設計人員引入了Optional<T>,這樣就不用返回眾所周知容易出問題的null了。Optional裡面幾種可以迫使你顯式地檢查值是否存在或處理值不存在的情形。

  • isPresent()將在Optional包含值的時候返回true, 否則返回false。
  • ifPresent(Consumer block)會在值存在的時候執行給定的程式碼塊。
  • T get()會在值存在時返回值,否則丟擲一個NoSuchElement異常。
  • T orElse(T other)會在值存在時返回值,否則返回一個預設值。

查詢元素

findAny方法將返回當前流中的任意元素。它可以與其他流操作結合使用。

例如,我們需要顯示的檢查是否存在一個名為‘Ron’的人並顯示其名稱就可以按照如下的程式碼操作。

list.stream()
        .filter(u->u.getName().equals("Ron"))
        .findAny()
        .ifPresent(u->System.out.println(u.getName()));

流水線將在後臺進行優化使其只需走一遍,並在利用短路找到結果時立即結束。

查詢第一個元素

有些流有一個出現順序(encounter order)來指定流中專案出現的邏輯順序(比如由List或排序好的資料列生成的流)。對於這種流,你可能想要找到第一個元素。為此有一個findFirst方法,它的工作方式類似於findany。

例如我們需要找到第一個isLeader為ture的物件並列印其名字,就可以按照如下的程式碼操作。

list.stream()
        .filter(u->u.isLeader())
        .findFirst()
        .ifPresent(u->System.out.println(u.getName()));

何時使用findFirst和findAny

你可能會想,為什麼會同時有findFirst和findAny呢?答案是並行。找到第一個元素在並行上限制更多。如果你不關心返回的元素是哪個,請使用findAny,因為它在使用並行流時限制較少。

參考:Java8實戰

相關推薦

JavaStream操作例項-篩選對映查詢匹配

準備工作 構建一個測試類,通過測試類先初始化一個數據源,具體如下。 public class TestObject { private String name; private String sex; private int ag

JavaStream簡介

流簡介 要討論流,我們先來談談集合,這是最容易上手的方式了。 Java 8中的集合支援一個新的stream方法,它會返回一個流(介面定義在java.util.stream.Stream裡)。那麼, 流到底是什麼呢?簡短的定義就是“從支援資料處理操作的源生成的元

Java-函數語言程式設計Stream

流使程式猿可以在抽象層上對集合進行操作。 從外部迭代到內部迭代 什麼是外部迭代和內部迭代呢? 個人認為,外和內是相對集合程式碼而言。 如果迭代的業務執行在應用程式碼中,稱之為外部迭代。 反之,迭代的業務執行在集合程式碼中,稱為內部迭代(函數語言程式設計)。 語言描述可能有點抽象,下面看例項。

nodeJs文件系統fsstream

writer pipe 常用事件 urn 種類型 發生 成功 fin console 一、簡介 本文將介紹node.js文件系統(fs)和流(stream)的一些API已經參數使用情況。 二、目錄 文件系統將介紹以下方法: 1.fs.readFile

封裝位元組byte[]操作類 c#

在網路通訊中,資料在網路傳輸的格式必須以位元組流的形式進行,因此需要我們對位元組流進行寫入和讀出的操作,下面將會封裝兩個類,用來將各種型別的資料寫入位元組流,和從位元組流中讀取各種型別的資料。如下讀取類:NetBufferReaderusing System; using S

nodeJs檔案系統fsstream

檔案系統(File System): 在Node中,檔案系統的互動是非常重要的,伺服器的本質就是將本地的檔案傳送給客戶端, Node通過fs模組來和檔案系統進行互動,該模組提供了一些標準的檔案訪問API類開啟、讀取、寫入檔案、以及與其互動。 要是用fs模組,首先要從核心模組中載入; 使用 co

nodejs筆記之stream

nis tab and 出錯 htm ons 設置 索引 進行 nodejs的stream有四種流類型: 可讀:Readable可寫:Writable可讀可寫:Duplex操作被寫入數據,然後讀出結果:Transform常用事件:data:有數據可讀時觸發end:沒有數據可

初學 Java webapplication例項

利用application實現簡單的聊天室 login.jsp完成功能: 接收使用者名稱,提交給chat.jsp chat.jsp完成功能 獲取登入使用者名稱,顯示歡迎資訊 從application物件中獲取所有使用者的聊天記錄,並顯示(使用application物件的g

Java註解Annotation——3 例項

本例子旨在使用自定義註解為實體打上標記,為自動生成 sql 提供依據,模擬 hibernate 的註解,至於註解的原理自己搜吧1.定義 Table 註解package test;  import java.lang.annotation.Documented;  import

跟我學 Java 8 新特性之 Stream 縮減操作

和前面兩篇文章一起服用,效果會更佳。通過對流API的基礎體驗Demo和關鍵知識點的講解,相信大家對流API都有一定的認識了,但是流API強大的功能,可不僅僅像前面兩篇文章中說的那樣簡單,大家應該注意到,在第二篇中,我對Stream介面進行介紹的時候,並沒有把他的全部方法都

跟我學 Java 8 新特性之 Stream 並行

隨著對流API認識的慢慢深入,本章我們要討論的知識點是流API裡面的並行流了。 在開始討論並行流之前,我先引發一下大家的思考,就你看到這篇文章的時間,你們是不是經常聽到,Intel i7 CPU什麼8核16執行緒,什麼Android手機8核4GB這種訊息,既然我們是處於

跟我學 Java 8 新特性之 Stream 關鍵知識點

我們的第一篇文章,主要是通過一個Demo,讓大家體驗了一下使用流API的那種酣暢淋漓的感覺。如果你沒有實踐,我還是再次呼籲你動手敲一敲,自己實實在跑一遍上一篇的Demo。 相信你的感受和理解也會隨之加深的。繼續探索流API的高階功能之前,我們先從介面級別全面瞭解一下流A

跟我學 Java 8 新特性之 Stream 收集

我們前面的五篇文章基本都是在說將一個集合轉成一個流,然後對流進行操作,其實這種操作是最多的,但有時候我們也是需要從流中收集起一些元素,並以集合的方式返回,我們把這種反向操作稱為收集。 流API也給我們提供了相應的方法。 如何在流中使用收集功能? 我們先看一看流API

跟我學 Java 8 新特性之 Stream 與迭代器,系列大結局

恭喜你們,馬上就要學完Java8 Stream流的一整系列了,其實我相信Stream流對很多使用Java的同學來說,都是一個知識盲點,因為這個原因,我才這麼細緻地講解Stream流的各個知識點,通過這一整個系列,我相信只要認真看了的同學,都已掌握的差不多了,就差實戰了。

黑馬程式設計師——Java IO操作規律總結File類Properties類序列

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 六、流操作規律總結  1.明確源和目的:   源:    字元流:FileReader(純文字檔案)。    位元組流:FileInputStream(

java基礎之I/O------------字元的檔案讀寫操作

一.流的概念: java的輸入輸出稱為流,流是一組有順序的集合。而流的本質則是資料傳輸 二.流的分類:                  1.根據處理的功能分為位元組流(InputStream,OutPutStrean)和字元流(Writer,Reader)  

【Selenium2+Java自動化3】-操作瀏覽的基本方法

臨時文件 mage 關閉 log 開始 str 打開 img bsp 前言   前面已經把環境搭建好了,這從這篇開始,正式學習selenium的webdriver框架。我們平常說的 selenium自動化,其實它並不是類似於QTP之類的有GUI界面的可視化工具,我們要學的是

Java IO 字節流與字符

減少 rgs 作文 設計 fileinput src != tro 關閉 概述 IO流用來處理設備之間的數據傳輸 Java對數據的操作時通過流的方式 Java用於操作流的對象都在IO包中 流按操作的數據分為:字節流和字符流 流按流向不同分為:輸入流和輸出流 IO流常用基類

Java IO 字節流與字符

length 相關操作 數組 new throws mce 存在 () put  Java的IO流分為字符流(Reader,Writer)和字節流(InputStream,OutputStream),字節流顧名思義字節流就是將文件的內容讀取到字節數組,然後再輸出到另一個文件

java 核心編程——IO之字符

sun logs printf file start ech read private per 1.字符流   1.1 所有文件的存儲都是字節的存儲,我們日常在磁盤上保存的其實並不是文件的字符,而是先把字符轉換成字節,再把這些字節儲存到磁盤。在讀取文件時,也是一個字節一個字