Java流(Stream)操作執行個體-篩選、映射、尋找匹配__Java

來源:互聯網
上載者:User

準備工作

構建一個測試類別,通過測試類別先初始化一個資料來源,具體如下。

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,"ron.zheng@tfschange.com",false),            new TestObject("KDS","W",10,"kds@qq.com",false),            new TestObject("BoDuo","W",30,"boduo@163.com",false),            new TestObject("CangJin","W",10,"cangjin@gmail.com",false),            new TestObject("XiaoZe","W",30,"xiaoze@hotmail.com",true),            new TestObject("James","M",10,"leblonjames@hotmail.com",true),            new TestObject("Allen","M",50,"allen.lei@tfschange.com",true),            new TestObject("Smith","M",10,"jr.smith@cel.com",true),            new TestObject("Wade","M",20,"dw.wade@cel.com",true),   new TestObject("Wade","M",20,"dw.wade@cel.com",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方法輸出的流的類型就是StreamString>。

我們來再看一個例子,我們把方法引用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實戰

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.