JAVA8之工具類Stream

一.    概述

        在jdk1.8中引入的新的對集合中數據的處理的--Stream流.該工具類常常被我們用來對集合中數據的篩選,處理等等,使用流可以大大的減少我們的代碼量,也是我們的代碼邏輯性更強,更容易明白每一步是在做什麼.

二.    特性

        1.    流不會存儲元素,遍歷完一次就等於消費完了.

        2.    流都是懶加載的,只有你用到結果的時候纔會去執行.

        3.    流只會操作數據,不會改變數據.

        4.    它採用的是內部迭代,即它會根據環境等因素確定如果去操作數據,我們只需要告訴我我們的目的.

三.    操作過程

    1.    創建操作(四種)

        1.1    通過集合創建

        先寫一個用戶類,重寫了equals和hashCode方法.

package com.yczuoxin.demo.stream;

import java.util.Objects;

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                                        new User("lisi",19),
                                        new User("wangwu",20),
                                        new User("zhaoliu",21));
        Stream<User> stream = list.stream();
        Stream<User> userStream = list.parallelStream();
    }
}

        1.2    通過數組創建

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        Integer[] ints = new Integer[5];
        Stream<Integer> integerStream = Arrays.stream(ints);
        String[] strings = new String[5];
        Stream<String> stringStream = Arrays.stream(strings);
    }
}

 

         1.3    通過值創建

package com.yczuoxin.demo.stream;

import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        Stream<String> stringStream = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu");
    }
}

         1.4    通過函數創建(該方法創建的是無限流,需要用limit來限制大小)

package com.yczuoxin.demo.stream;

import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        // 迭代
        Stream<Integer> stream3 = Stream.iterate(2, (x) -> x * 2).limit(4);
        stream3.forEach(System.out::println);

        System.out.println("-------------");

        // 生成
        Stream<Double> stream4 = Stream.generate(Math::random).limit(4);
        stream4.forEach(System.out::println);
    }
}

         1.5    通過文件創建

        先創建一個文件

package com.yczuoxin.demo.stream;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        try(Stream lines = Files.lines(Paths.get("E:\\code\\test\\demo\\src\\main\\java\\com\\yczuoxin\\demo\\stream\\test.properties"),Charset.defaultCharset())){
            lines.forEach(System.out::println);
        }catch(IOException e){
        }
    }
}

    2.    中間操作

            中間操作就是對流進行操作.

         2.1    篩選

               2.1.1    filter(Predicate p)方法

                          在流中篩選一些符合要求的元素.

               2.1.2    distinct()方法

                   在流中利用hashCode的equals方法去除某些相同的元素.

               2.1.3    limit(long maxSize)方法

                        在流中數據達到最大值時截斷流.

               2.1.4    skip(long n)方法

                        丟棄掉流中的前n個元素,如果流中數據沒有達到n,則返回一個空流.

                看下代碼示例:

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.List;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                                        new User("lisi",19),
                                        new User("wangwu",20),
                                        new User("wangwu",20),
                                        new User("zhaoliu",21));
        // 去重
        list.stream().distinct()
                // 篩選出年齡大於19的用戶
                .filter(user -> user.getAge() >= 19)
                // 截取兩個用戶
                .limit(2)
                // 輸出用戶
                .forEach(System.out::println);
    }
}

            2.2    映射

                2.2.1    map(Function function)方法

                        接受一個函數入參,該函數會用在每個元素上,並將其結果映射成一個新的元素.

                2.2.2    flatMap(Function function)方法

                        接受一個函數入參,該函數會用在每個元素上,並將流中每個元素換到另一個流中.然後將所有的流連在一起.

            下面看示例代碼

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
        // 將所有的集合流映射到一個流裏面
        listStream.flatMap(list -> list.stream()).
                // 對流裏面的值都加10並輸出
                map(integer -> integer + 10).forEach(System.out::println);
    }
}

 

將3個數組內的值全部都融合在一個數組輸出.這就是flatMap的作用.

            2.3      排序

               2.3.1      sort()方法

                             按照自然規則排序

               2.3.2      sort(Comparator comparator)方法

                             按照給定的規則排序

                看下示例代碼

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                new User("lisi",21),
                new User("wangwu",19),
                new User("zhaoliu",20));
        list.stream().map(x -> x.getAge()).sorted().forEach(System.out::println);
        list.stream().sorted(Comparator.comparing(x->x.getName())).forEach(System.out::println);
    }
}

先使用自然排序對用戶的年齡進行映射,然後對其排序輸出.然後使用自己定義的排序規則對用戶根據名字開的開頭字母進行排序.

    3.    終止操作

              該操作和會使流進行操作然後獲得結果.

            3.1      匹配

                  3.1.1      count()方法

                        返回該流存在的元素個數,返回值類型爲long類型.

                  3.1.2      findFirst()方法.

                        返回該流中第一個元素.如果沒有不會報空指針,返回值爲Optional類型,空時返回empty.

                  3.1.3      findAny()方法

                        返回流中任意一個元素.如果沒有不會報空指針,返回值爲Optional類型,空時返回empty.

                  3.1.4      allMatch(Predicate predicate)方法

                        返回流中所有的元素是否滿足Predicate條件,返回值爲布爾類型(boolean)

                  3.1.5      anyMatch(Predicate predicate)方法

                        返回流中的元素是否有滿足Predicate條件,返回值爲布爾類型(boolean)

                  3.1.6      noneMatch(Predicate predicate)方法

                        返回流中的元素是否都不滿足Predicate條件,返回值爲布爾類型(boolean)

                  3.1.7      max(Comparator comparator)方法

                        返回流中通過Comparator比較後的最大值,返回值爲Optional類型.

                  3.1.8      min(Comparator comparator)方法

                        返回流中通過Comparator比較後的最小值,返回值爲Optional類型.

                  3.1.9      forEach(Consumer consumer)方法

                        對流中所有的元素進行迭代操作(內部迭代).操作順序是並行執行.一般情況下還是按順序執行.

                  3.1.10     forEachOrdered(Consumer consumer)方法

                        對流中所有的元素進行迭代操作(內部迭代).操作順序是按照流的順序執行.效率沒有前者高.

            示例代碼:

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                new User("lisi",21),
                new User("wangwu",19),
                new User("zhaoliu",20));
        // 過濾出沒有元素的流試探會不會報空指針異常
        System.out.println(list.stream().map(x -> x.getAge()).sorted().filter(x -> x > 21).findAny());
        // 判斷是否全部用戶年齡都大於19
        System.out.println(list.stream().allMatch(user -> user.getAge() > 19));
        // 判斷是否至少有一位用戶年齡都大於19
        System.out.println(list.stream().anyMatch(user -> user.getAge() > 19));
        // 判斷是否全部用戶年齡都不大於19
        System.out.println(list.stream().noneMatch(user -> user.getAge() > 19));
        // 求出用戶年齡的最大值.
        System.out.println(list.stream().max(Comparator.comparing(x->x.getAge())));
        // 利用Comparator將用戶年齡比較大小反寫,利用最大值求出最小值
        System.out.println(list.stream().max((x,y) -> y.getAge() - x.getAge()));
    }
}

            3.2      歸約

                 3.2.1      reduce(T identity, BinaryOperator accumulator)

                        歸約是將集合中的所有元素經過指定運算(加減乘除等),摺疊成一個元素輸出.返回一個T類型的值.第一個值爲初始值.

                 3.2.2      reduce(BinaryOperator accumulator)

                        歸約是將集合中的所有元素經過指定運算(加減乘除等),摺疊成一個元素輸出.返回一個Optional類型的值.

          示例代碼:

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.List;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                new User("lisi",21),
                new User("wangwu",19),
                new User("zhaoliu",20));
        System.out.println(list.stream().map(x -> x.getAge()).reduce(Integer::sum));
        System.out.println(list.stream().map(x -> x.getAge()).reduce(0,Integer::sum));
    }
}

上面是對於所有用戶年齡的求和.

            3.3      集合collect

            將流轉化成集合的形式.以下是示例代碼:

package com.yczuoxin.demo.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamTest {
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("zhangsan",18),
                new User("lisi",21),
                new User("wangwu",19),
                new User("wangwu",19),
                new User("zhaoliu",20));
        list.stream().collect(Collectors.toSet()).forEach(System.out::println);
    }
}

利用set集合來對list進行去重操作並將list轉化成了set.如何具體使用可以去了解Collectors工具類.其對於流還有分組的功能,就如數據庫操作的groupBy一樣.

發佈了1 篇原創文章 · 獲贊 35 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章