Java中Stream流相關介紹

什麼是Stream?

Stream是JDK8 API的新成員,它容許以聲明性方式處理數據集合java

特色

  1. 代碼簡潔: 函數式編程寫出的代碼簡潔且意圖明確,使用stream接口讓你今後告別for循環
  2. 多核友好: Java函數式編程使得編寫並行程序從未如此簡單,你須要的所有就是調用一下方法

爲何要使用Stream API?

  • 實際開發中,項目中多數數據源都來自於MySQL,Oracle等.但如今數據源能夠更多了,有MongoDB,Redis等,而這些NoSQL的數據就須要Java層面去處理程序員

  • Stream和Collection集合的區別:Collection是一種靜態的內存數據結構,而Stream是有關計算的.前者是主要面向內存,存儲在內存中,後者主要是面向CPU,經過CPU實現計算編程

    注意:api

    1. Stream本身不會存儲元素
    2. Stream不會改變源對象.相反,他們會返回一個持有結果的新Stream
    3. Stream操做是延遲執行的.這意味着他們會等到須要結果的時候才執行

步驟

  1. 建立Stream數組

    一個數據源(集合,數組等),獲取一個流markdown

  2. 中間操做數據結構

    一箇中間操做鏈,對數據源的數據進行處理dom

  3. 終止操做ide

    一旦執行終止操做,就執行中間操做鏈,併產生結果.以後,不會再被使用函數式編程

Stream的實例化

/**
 * @PROJECT_NAME: myTest
 * @DESCRIPTION:  Stream的方法測試
 * @USER: 羅龍達
 * @DATE: 2021/2/21 2:33
 */
public class streamTest {

    @Test
    public void createStream(){
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jk");
        //1. 經過集合建立stream   --  返回一個順序流
        Stream<String> listStream = strings.stream();

        //返回一個並行流
        Stream<String> paraStream = strings.parallelStream();

        //2. 經過數組建立stream
        IntStream arrStream = Arrays.stream(new int[]{1, 3, 45, 6, 877, 12});

        //3. 經過Stream的of()方法
        Stream<Integer> integerStream = Stream.of(1, 3, 5, 7, 9);

        //4. 建立無限流
        Stream.iterate(0,t -> t+2).limit(10).forEach(System.out::println);

        //5. 生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }
}

中間操做的部分API測試

@Test
    public void InOperationTest() {
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "abc", "jk");
        //1. 經過集合建立stream   --  返回一個順序流
        Stream<String> listStream = strings.stream();
        System.out.println("-----------測試filter--------------");
        /**
         *  filter(Predicate predicate) -- 接收lambda,從流中排除某些元素
         *  查詢列表中不爲null的元素
         */
        //
        listStream.filter(s -> !s.equals("")).forEach(System.out::println);
        System.out.println("--------------測試limit------------");
        /**
         *limit(n)  -- 截斷流,使元素不超過給定數量
        */
        strings.stream().limit(3).forEach(System.out::println);

        System.out.println("-------------測試skip--------------");
        /**
         *skip(n)  --  跳過元素,返回一個扔掉了前n個元素的流,若是流中元素不足n個,則返回一個空流
         */
        strings.stream().skip(3).forEach(System.out::println);

        System.out.println("------------測試distinct-----------");
        /**
         *distinct()  --  篩選,經過流所產生元素的hashCode()和equals()去除重複元素
         */
        strings.stream().distinct().forEach(System.out::println);
    }

Map映射API的部分測試

@Test
    public void mapTest(){
        System.out.println("----------------將字符串轉換成大寫---------------");
        List<String> strings = Arrays.asList("aaa", "bb", "cccc", "d","eeeee","ff");
        /**
         * 接受一個函數做爲參數,將元素轉換成其餘形式或提取信息,該函數會被應用到每一個元素上,並將其映射成一個新的元素
         */
        strings.stream().map(String::toUpperCase).forEach(System.out::println);
        System.out.println("------------字符串長度大於3的元素的大寫-----------");

        /**
         * 返回字符串長度大於3的元素的大寫
         */
        strings.stream().filter(s -> s.length() >3).map(String::toUpperCase).forEach(System.out::println);

        /**
         * flatMap(Function f) -- 接收一個函數做爲參數,將流中的每一個值都換成另外一個流,而後把全部流鏈接成一個流。
         */
        strings.stream().flatMap(streamTest::fromStringToStream).forEach(System.out::println);
    }

    //將字符串中的多個字符構成的集合轉換爲對應的流
    public static Stream<Character> fromStringToStream(String s){
        ArrayList<Character> list = new ArrayList<>();
        for (char c : s.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

map與flatMap的區別

  • 從上面例子能夠看出,map 生成的是個 1:1 映射,每一個輸入元素,都按照規則轉換成爲另一個元素。還有一些場景,是一對多映射關係的,這時須要 flatMap。
  • flatMap 把 inpuStream 中的層級結構扁平化,就是將最底層元素抽出來放到一塊兒,最終 output 的新 Stream 裏面已經沒有 List 了,都是直接的數字。

排序API測試

@Test
    public void sortTest() {
        List<Integer> list = Arrays.asList(23, 45, -12, 2, 7, 89, 5);
        System.out.println("----------從小到大排序測試---------");
        list.stream().sorted().forEach(System.out::println);
        System.out.println("----------從大到小排序測試---------");
        list.stream().sorted((i1, i2) -> i2 - i1).forEach(System.out::println);
    }

終止操做的部分API測試

@Test
    public void termOperationTest(){
        List<Integer> list = Arrays.asList(23, 45, -12, 2, 7, 89, 5);
        System.out.println("-----------allMatchTest-------------");
        /**
         * allMatch(Predicate predicate)  --  檢查是否匹配全部元素
         */
        boolean allMatch = list.stream().allMatch(integer -> integer > 0);
        System.out.println(allMatch);

        System.out.println("-----------anyMatchTest-------------");
        /**
         * allMatch(Predicate predicate)  --  檢查是否匹配全部元素
         */
        boolean anyMatch = list.stream().anyMatch(integer -> integer > 0);
        System.out.println(anyMatch);

        System.out.println("----------noneMatchTest-------------");
        /**
         * noneMatch(Predicate predicate)  --  檢查是否沒有匹配的元素
         */
        boolean noneMatch = list.stream().noneMatch(integer -> integer > 0);
        System.out.println(noneMatch);

        System.out.println("----------findFirstTest-------------");
        /**
         * findFirst()  --  返回流中第一個元素
         */
        Optional<Integer> first = list.stream().findFirst();
        System.out.println(first);
        System.out.println("------------findAnyTest-------------");
        /**
         * findAny()  --  返回流中任一元素
         */
        Optional<Integer> any = list.parallelStream().findAny();
        System.out.println(any);

        System.out.println("--------------countTest-------------");
        /**
         * count()  --  返回流中元素的總個數
         */
        long count = list.stream().filter(i -> i > 0).count();
        System.out.println(count);

        System.out.println("------------max / min Test----------");
        /**
         * max/min(Comparator comparator)  --  返回流中最大值 / 最小值
         */
        Optional<Integer> max = list.stream().max((i1, i2) -> i1 - i2);
        System.out.println("max = " + max);
        Optional<Integer> min = list.stream().min((i1, i2) -> i1 - i2);
        System.out.println("min = " + min);

        System.out.println("--------------forEachTest------------");
        /**
         * forEach(Consumer c)  --  內部迭代
         */
//        list.stream().forEach(System.out::println);
        list.forEach(System.out::println);
    }

規約操做部分API測試

@Test
    public void reduceTest(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        /**
         * reduce(T identity, BinaryOperator) -- 能夠將流中元素反覆結合起來,獲得一個值
         */
        Integer reduce = list.stream().reduce(0, Integer::sum);
        System.out.println("reduce = " + reduce);

        /**
         * reduce(BinaryOperator)  -- 能夠將流中元素反覆結合起來,獲得一個值,返回optional
         */
        Optional<Integer> reduce2 = list.stream().reduce(Integer::sum);
        Optional<Integer> reduce3 = list.stream().reduce((i1, i2) -> i1 + i2);
        System.out.println("reduce2 = " + reduce2);
        System.out.println("reduce3 = " + reduce3);
    }

collect部分API測試

@Test
public void collectTest(){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    /**
     *collect(Collector c) 將流轉換爲其餘形式.接受一個Collector接口的實現
     * 查找大於4的數字,結果返回一個list / set
     */
    List<Integer> collectList = list.stream().filter(i -> i > 4).collect(Collectors.toList());
    collectList.forEach(System.out::println);
    Set<Integer> collectSet = list.stream().filter(i -> i > 4).collect(Collectors.toSet());
    collectSet.forEach(System.out::println);

}

Optional類

  • 到目前爲止,臭名昭著的空指針異常是致使Java應用程序失敗的最多見緣由.

    之前,爲了解決空指針異常,Google公司著名的Guava項目引入了Optional類,Guava經過使用檢查空值的方式來防止代碼污染,鼓勵程序員寫更乾淨的代碼.受到Google Guava的啓發,Optional類已經成爲Java 8 類庫的一部分

  • Optional 類是一個容器類,他能夠保存類型T的值,表明這個值存在,或者僅僅保存null,表示這個值不存在.原來用null表示一個值不存在,如今Optional能夠更好地表達這個概念.而且能夠避免空指針異常

  • Optional類的Javadoc描述以下: 這是一個能夠爲null的容器對象.若是值存在在isPresent()方法會返回true,調用get()方法會返回該對象

相關方法

# 1 建立Optional類對象的方法
- Optional.of(T t): 建立一個Optional實例,`t必須非空`
- Optional.empty(): 建立一個空的Optional實例
- Optional.ofNullable(T t): t能夠爲null

# 2 判斷Optional容器中是否包含對象: 
- boolean isPresent(): 判斷是否包含對象
- void ifPresent(Consumer consumer): 若是有值,就執行Consumer接口的實現代碼,而且該值會做爲參數傳給它

# 3 獲取Optional容器的對象
- T get(): 若是調用對象包含值,返回該值,不然拋異常
- T orElse(): 若是有值則將其返回,不然返回指定的other對象
- T orElseGet(Supplier other): 若是有值將其返回,不然返回由Supplier接口實現提供的對象
- T orElseThrow(Supplier exceptionSupplier): 若是有值則將其返回,不然拋出由Supplier接口實現提供的異常

相關方法代碼測試

  • Girl實體類
public class Girl {
    public Girl() {
    }

    public Girl(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • Boy實體類
public class Boy {
    private Girl girlFriend;
    private String name;

    public Boy() {
    }

    public Boy(Girl girlFriend, String name) {
        this.girlFriend = girlFriend;
        this.name = name;
    }

    public Girl getGirlFriend() {
        return girlFriend;
    }

    public void setGirlFriend(Girl girlFriend) {
        this.girlFriend = girlFriend;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
@Test
    public void OptionalTest(){
        Girl girl = new Girl();
        girl=null;
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println("optionalGirl = " + optionalGirl);
    }

    //原始的getName方法
    public String getGirlName(Boy boy){
        return boy.getGirlFriend().getName();
    }

    //優化後的getName方法
    public String getGirlNameAfterOptimizing(Boy boy){
        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        //此時boy1必定非空
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("楊冪"), "我"));
        Girl girlFriend = boy1.getGirlFriend();
        Optional<Girl> girlFriend1 = Optional.ofNullable(girlFriend);
        //girlOption必定非空
        Girl girlOptional = girlFriend1.orElse(new Girl("趙麗穎"));


        return "女友的名字 : " + girlOptional.getName();
    }

    @Test
    public void testGetName(){
        Boy boy = new Boy();
//        boy = null;
        boy.setGirlFriend(null);
//        boy.setGirlFriend(new Girl("迪麗熱巴"));
        System.out.println(getGirlNameAfterOptimizing(boy));
    }
相關文章
相關標籤/搜索