JDK1.8新特性Stream流式操作

2020-09-25 11:00:31

一. 前言

隨著Java的發展,越來越多的企業開始使用JDK1.8 版本。JDK1.8 是自 JDK1.5之後最重要的版本,這個版本包含語言、編譯器、庫、工具、JVM等方面的十多個新特性。本次文章將著重學習Stream

StreamJDK1.8 中處理集合的關鍵抽象概念,LambdaStreamJDK1.8新增的函數語言程式設計最有亮點的特性了,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。使用Stream API 對集合資料進行操作,就類似於使用SQL執行的資料庫查詢。Stream 使用一種類似用 SQL 語句從資料庫查詢資料的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。Stream API可以極大提高Java程式設計師的生產力,讓程式設計師寫出高效率、乾淨、簡潔的程式碼。

這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。

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

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

簡而言之,Stream API提供了一種高效且易於使用的處理資料的方式。


二. 什麼是Stream

1.Stream(流)是一個來自資料來源的元素佇列並支援聚合操作。

  • 元素是特定型別的物件,形成一個佇列。 Java中的Stream並不會儲存元素,而是按需計算。
  • 資料來源 流的來源。 可以是集合,陣列,I/O channel, 產生器generator 等。
  • 聚合操作 類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted等。

2.和以前的Collection操作不同, Stream操作還有兩個基礎的特徵:

  • Pipelining: 中間操作都會返回流物件本身。 這樣多個操作可以串聯成一個管道, 如同流式風格(fluent style)。 這樣做可以對操作進行優化, 比如延遲執行(laziness)和短路( short-circuiting)。
  • 內部迭代: 以前對集合遍歷都是通過Iterator或者For-Each的方式, 顯式的在集合外部進行迭代, 這叫做外部迭代。 Stream提供了內部迭代的方式, 通過存取者模式(Visitor)實現。

特點:

  1. Stream 不是資料結構,不會儲存資料。
  2. Stream 不會修改原來的資料來源,它會將操作後的資料儲存到另外一個物件中。(保留意見:畢竟peek方法可以修改流中元素)
  3. 惰性求值,流在中間處理過程中,只是對操作進行了記錄,並不會立即執行,需要等到執行終止操作的時候才會進行實際的計算。

三. 關於Stream API

1. Stream API分類

Stream 操作分為中間操作或者終止操作兩種,終止操作返回一特定型別的計算結果,而中間操作返回Stream本身,Stream 的操作型別具體分類如下:
img

解釋:

  • 無狀態:指元素的處理不受之前元素的影響;

  • 有狀態:指該操作只有拿到所有元素之後才能繼續下去。

  • 非短路操作:指必須處理所有元素才能得到最終結果;

  • 短路操作:指遇到某些符合條件的元素就可以得到最終結果,如 A || B,只要A為true,則無需判斷B的結果。

2. 如何使用Stream流?

使用Stream流分為三步。

  • 建立Stream

    一個資料來源(如:集合、陣列),獲取一個Stream流。

  • 中間操作

    一箇中間操作鏈,對資料來源(如:集合、陣列)的資料進行處理。

  • 終止操作

    一個終止操作,執行中間操作鏈,併產生一個計算結果。

3. Stream的中間操作和結束操作

  • 中間操作

filter: 過濾流,過濾流中的元素,返回一個符合條件的Stream

map: 轉換流,將一種型別的流轉換為另外一種流。(mapToInt、mapToLong、mapToDouble 返回int、long、double基本型別對應的Stream)

flatMap:簡單的說,就是一個或多個流合併成一個新流。(flatMapToInt、flatMapToLong、flatMapToDouble 返回對應的IntStream、LongStream、DoubleStream流。)

distinct: 返回去重的Stream。

sorted: 返回一個排序的Stream。

peek: 主要用來檢視流中元素的資料狀態。

limit: 返回前n個元素資料組成的Stream。屬於短路操作

skip: 返回第n個元素後面資料組成的Stream。

  • 結束操作

forEach: 迴圈操作Stream中資料。

toArray: 返回流中元素對應的陣列物件。

reduce: 聚合操作,用來做統計。

collect: 聚合操作,封裝目標資料。

min、max、count: 聚合操作,最小值,最大值,總數量。

anyMatch: 短路操作,有一個符合條件返回true。

allMatch: 所有資料都符合條件返回true。

noneMatch: 所有資料都不符合條件返回true。

findFirst: 短路操作,獲取第一個元素。

findAny: 短路操作,獲取任一元素。

forEachOrdered: 暗元素順序執行迴圈操作。


四. 如何獲取Stream流

在 Java 8 中, 集合介面有兩個方法來生成流:

  • stream() − 為集合建立序列流。
  • parallelStream() − 為集合建立並行流。

1. 常見幾種集合流的建立

/**
 * stream,獲取各種集合的stream流
 */
@Test
public void testCollectionStream(){
    //List集合  
    List<String> stringList = new ArrayList<>();
    //Set集合
    Set<String> stringSet = new HashSet<>();
    //Map集合
    Map<String,Object> stringObjectMap = new HashMap<>();
    //陣列
    String[] stringArray = {"張三三","李四","王五","王五","趙八",};

    //通過list獲取stream流
    Stream<String> streamList = stringList.stream();
    //通過set獲取stream流
    Stream<String> streamSet = stringSet.stream();
    //通過map獲取stream流
    Stream<String> streamMap = stringObjectMap.keySet().stream();
    //通過array獲取stream流
    Stream<String> streamArray1 = Stream.of(stringArray);
}

2. 構造流的幾種常見方法

@Test
public void testCollectionStream(){
   // 1. Individual values
  Stream stream = Stream.of("a", "b", "c");
  
  // 2. Arrays
  String[] strArray = new String[]{"a", "b", "c"};
  stream = Stream.of(strArray);
  stream = Arrays.stream(strArray);
  
  // 3. Collections
  List<String> list = Arrays.asList(strArray);
  stream = list.stream();
  
}

五. Stream在程式碼中的使用方式

關於Stream的常見操作方式,主要分為兩大類: 中間操作和終止操作 ,接下來就通過這兩大分類,講解下具體的語法用法。

1. 流的中間操作

1.1 篩選過濾

  • filter:過濾流中的某些元素

       /**
         * filter 方法 , 返回符合過濾條件的值
         */
        @Test
        public void testFilter() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.stream().filter(e -> e.contains("張")).forEach(System.out::println);
        }
    

    • filter多個過濾篩選條件
       /**
      * list集合stream流式操作
      */
     @Test
     public void testStreamList() {
         List<String> list = new ArrayList<>();
         list.add("張三三");
         list.add("李四");
         list.add("王五");
         list.add("孫七");
         list.add("趙八");
         list.stream().filter(e -> e.startsWith("張")) //過濾所有姓張的人
                 .filter(e -> e.length() == 3) //過濾所有姓名是3個字的人
                 .forEach(System.out::println); //遍歷列印,System.out::println表明System.out呼叫println列印方法
     }
    
  • limit(n):獲取前n個元素

     /**
         * limit 方法 ,返回前n個元素資料值組成的Stream。
         */
        @Test
        public void testLimit() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            list.stream().limit(3).forEach(System.out::println); //取前3個
        }
    
  • skip(n):跳過n元素,配合limit(n)可實現分頁

     /**
         * skip方法 ,跳過前n個元素的中間流操作,返回剩下的值。
         */
        @Test
        public void testSkip() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            //list.stream().skip(3).forEach(System.out::println); //跳過前3個
            list.stream().skip(3).limit(2).forEach(System.out::println); //skip+limit實現分頁
        }
    
  • distinct:通過流中元素的 hashCode() 和 equals() 去除重複元素

     /**
         * distinct, 返回去重的Stream
         */
        @Test
        public void testDistinct() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            list.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);
        }
    

1.2 排序

  • sorted():自然排序,流中元素需實現Comparable介面

     /**
         * sorted: 返回一個排序的Stream
         */
        @Test
        public void testSorted() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            list.stream().distinct().sorted().collect(Collectors.toList()).forEach(System.out::println);
        }
    
  • sorted(Comparator com):客製化排序,自定義Comparator排序器

1.3 對映

  • map:接收一個函數作為引數,該函數會被應用到每個元素上,並將其對映成一個新的元素。
/**
    * 遍歷map集合,擷取substring(2)開始的值
    */
   @Test
   public void testMap() {
       List<String> list = new ArrayList<>();
       list.add("張三三");
       list.add("李四");
       list.add("王五");
       list.add("孫七");
       list.add("趙八");
       list.add("王二麻子");
       Stream<String> stream = list.stream().map(e -> e.substring(2));
       stream.forEach(System.out::println);
   }
  • forEach:ForEach流式遍歷集合

      /**
         * forEach, ForEach流式遍歷list集合
         */
        @Test
        public void testForEach() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.stream().forEach(System.out::println);
        }
    

2. 流的終止操作

2.1 匹配、聚合操作

  • allMatch:接收一個 Predicate 函數,當流中每個元素都符合該斷言時才返回true,否則返回false

     /**
         * allMatch:接收一個 Predicate 函數,當流中每個元素都符合該斷言時才返回true,否則返回false
         */
        @Test
        public void testAllMatch() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            boolean b = list.stream()
                    .allMatch(e -> list.size() > 8);
            System.out.println("b = " + b);
        }
    
  • noneMatch:接收一個 Predicate 函數,當流中每個元素都不符合該斷言時才返回true,否則返回false

        /**
         * noneMatch: 接收一個 Predicate 函數,當流中每個元素都不符合該斷言時才返回true,否則返回false
         */
        @Test
        public void testNoneMatch() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            boolean b = list.stream().noneMatch(e->e.equals("張三"));
            System.out.println("b = " + b);
        }
    
  • anyMatch:接收一個 Predicate 函數,只要流中有一個元素滿足該斷言則返回true,否則返回false

    /**
         * anyMatch:接收一個 Predicate 函數,只要流中有一個元素滿足該斷言則返回true,否則返回false
         */
        @Test
        public void testAnyMatch() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            boolean b = list.stream().anyMatch(e -> e.equals("王二麻子"));
            System.out.println("b = " + b);
        }
    
  • findFirst:返回流中第一個元素

     /**
         * findFirst:返回流中第一個元素
         */
        @Test
        public void testFindFirsth() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            Optional<String> first = list.stream().findFirst();
            System.out.println("first = " + first.get());
        }
    
  • findAny:返回流中的任意元素

        /**
         * findAny:返回流中第一個元素
         */
        @Test
        public void testFindAny() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("李四");
            list.add("王五");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            Optional<String> any = list.stream().findAny();
            System.out.println("any = " + any.get());
        }
    
  • count:返回流中元素的總個數

     /**
         * count,獲取List集合的長度
         */
        @Test
        public void testCount() {
            List<String> list = new ArrayList<>();
            list.add("張三三");
            list.add("李四");
            list.add("王五");
            list.add("孫七");
            list.add("趙八");
            list.add("王二麻子");
            long count = list.stream().count();
            System.out.println("count = " + count);
            int size = list.size();
            System.out.println("size = " + size);
        }
    
  • max:返回流中元素最大值

    /**
         * max:返回流中元素最大值
         */
        @Test
        public void testMax() {
            List<Integer> list = new ArrayList<>();
            list.add(11);
            list.add(22);
            list.add(33);
            list.add(44);
            list.add(55);
            list.add(66);
            list.add(77);
            list.add(88);
            Integer integer = list.stream().max(Integer::compareTo).get();
            System.out.println("integer = " + integer);
        }
    
  • min:返回流中元素最小值

    /**
     * min:返回流中元素最小值
     */
    @Test
    public void testMin() {
        List<Integer> list = new ArrayList<>();
        list.add(11);
        list.add(22);
        list.add(33);
        list.add(44);
        list.add(55);
        list.add(66);
        list.add(77);
        list.add(88);
        Integer integer = list.stream().min(Integer::compareTo).get();
        System.out.println("integer = " + integer);
        list.stream().limit(1).limit(2).distinct().skip(3).filter(f -> f.equals(55)).forEach(System.out::println);
    }
    

2.2 Collector 工具庫:Collectors

  • Collectors

    Student s1 = new Student("aa", 10,1);
    Student s2 = new Student("bb", 20,2);
    Student s3 = new Student("cc", 10,3);
    List<Student> list = Arrays.asList(s1, s2, s3);
      
    //裝成list
    List<Integer> ageList = list.stream().map(Student::getAge).collect(Collectors.toList()); // [10, 20, 10]
      
    //轉成set
    Set<Integer> ageSet = list.stream().map(Student::getAge).collect(Collectors.toSet()); // [20, 10]
      
    //轉成map,注:key不能相同,否則報錯
    Map<String, Integer> studentMap = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge)); // {cc=10, bb=20, aa=10}
      
    //字串分隔符連線
    String joinName = list.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")")); // (aa,bb,cc)
      
    //聚合操作
    //1.學生總數
    Long count = list.stream().collect(Collectors.counting()); // 3
    //2.最大年齡 (最小的minBy同理)
    Integer maxAge = list.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get(); // 20
    //3.所有人的年齡
    Integer sumAge = list.stream().collect(Collectors.summingInt(Student::getAge)); // 40
    //4.平均年齡
    Double averageAge = list.stream().collect(Collectors.averagingDouble(Student::getAge)); // 13.333333333333334
    // 帶上以上所有方法
    DoubleSummaryStatistics statistics = list.stream().collect(Collectors.summarizingDouble(Student::getAge));
    System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage());
      
    //分組
    Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors.groupingBy(Student::getAge));
    //多重分組,先根據型別分再根據年齡分
    Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getType, Collectors.groupingBy(Student::getAge)));
      
    //分割區
    //分成兩部分,一部分大於10歲,一部分小於等於10歲
    Map<Boolean, List<Student>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
      
    //規約
    Integer allAge = list.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get(); //40  
    

六、Stream操作程式碼

為了方便小夥伴們看到這篇部落格時,學習的更加輕鬆,這裡貼出原始碼,小夥伴們學習是可貼到IDEA執行檢視Stream過濾篩選的結果,以此對Stream的流式操作更加熟悉。

package com.java8.example.chapter3;

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @desc: Stream流式操作
 * @author: cao_wencao
 * @date: 2020-09-17 15:24
 */
public class TestStreamList {

    /**
     * list集合stream流式操作
     */
    @Test
    public void testStreamList() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.stream().filter(e -> e.startsWith("張")) //過濾所有姓張的人
                .filter(e -> e.length() == 3) //過濾所有姓名是3個字的人
                .forEach(System.out::println); //遍歷列印,System.out::println表明System.out呼叫println列印方法
    }

    /**
     * stream,獲取各種集合的stream流
     */
    @Test
    public void testCollectionStream() {
        List<String> stringList = new ArrayList<>();
        Set<String> stringSet = new HashSet<>();
        Map<String, Object> stringObjectMap = new HashMap<>();
        String[] stringArray = {"張三三", "李四", "王五", "王五", "趙八",};

        //通過list獲取stream流
        Stream<String> streamList = stringList.stream();
        //通過set獲取stream流
        Stream<String> streamSet = stringSet.stream();
        //通過map獲取stream流
        Stream<String> streamMap = stringObjectMap.keySet().stream();
        //通過array獲取stream流
        Stream<String> streamArray1 = Stream.of(stringArray);

    }

    /**
     * forEach, ForEach流式遍歷list集合
     */
    @Test
    public void testForEach() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.stream().forEach(System.out::println);
    }

    /**
     * filter 方法 , 返回符合過濾條件的值
     */
    @Test
    public void testFilter() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.stream().filter(e -> e.contains("張")).forEach(System.out::println);
    }

    /**
     * 遍歷map集合,擷取substring(2)開始的值
     */
    @Test
    public void testMap() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        Stream<String> stream = list.stream().map(e -> e.substring(2));
        stream.forEach(System.out::println);
    }

    /**
     * count,獲取List集合的長度
     */
    @Test
    public void testCount() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        long count = list.stream().count();
        System.out.println("count = " + count);
        int size = list.size();
        System.out.println("size = " + size);
    }

    /**
     * limit 方法 ,返回前n個元素資料值組成的Stream。
     */
    @Test
    public void testLimit() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        list.stream().limit(3).forEach(System.out::println); //取前3個
    }

    /**
     * skip方法 ,跳過前n個元素的中間流操作,返回剩下的值。
     */
    @Test
    public void testSkip() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        //list.stream().skip(3).forEach(System.out::println); //跳過前3個
        list.stream().skip(3).limit(2).forEach(System.out::println); //skip+limit實現分頁
    }

    /**
     * collect,將流轉化為集合
     */
    @Test
    public void testCollect() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        List<String> collect = list.stream().skip(3).limit(2).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }

    /**
     * distinct, 返回去重的Stream
     */
    @Test
    public void testDistinct() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        list.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);
    }

    /**
     * sorted: 返回一個排序的Stream
     */
    @Test
    public void testSorted() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        list.stream().distinct().sorted().collect(Collectors.toList()).forEach(System.out::println);
    }

    /**
     * anyMatch:接收一個 Predicate 函數,只要流中有一個元素滿足該斷言則返回true,否則返回false
     */
    @Test
    public void testAnyMatch() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        boolean b = list.stream().anyMatch(e -> e.equals("王二麻子"));
        System.out.println("b = " + b);
    }

    /**
     * noneMatch: 接收一個 Predicate 函數,當流中每個元素都不符合該斷言時才返回true,否則返回false
     */
    @Test
    public void testNoneMatch() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        boolean b = list.stream().noneMatch(e->e.equals("張三"));
        System.out.println("b = " + b);
    }

    /**
     * allMatch:接收一個 Predicate 函數,當流中每個元素都符合該斷言時才返回true,否則返回false
     */
    @Test
    public void testAllMatch() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        boolean b = list.stream()
                .allMatch(e -> list.size() > 8);
        System.out.println("b = " + b);
    }

    /**
     * findFirst:返回流中第一個元素
     */
    @Test
    public void testFindFirsth() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        Optional<String> first = list.stream().findFirst();
        System.out.println("first = " + first.get());
    }


    /**
     * findAny:返回流中第一個元素
     */
    @Test
    public void testFindAny() {
        List<String> list = new ArrayList<>();
        list.add("張三三");
        list.add("李四");
        list.add("李四");
        list.add("王五");
        list.add("王五");
        list.add("孫七");
        list.add("趙八");
        list.add("王二麻子");
        Optional<String> any = list.stream().findAny();
        System.out.println("any = " + any.get());
    }

    /**
     * max:返回流中元素最大值
     */
    @Test
    public void testMax() {
        List<Integer> list = new ArrayList<>();
        list.add(11);
        list.add(22);
        list.add(33);
        list.add(44);
        list.add(55);
        list.add(66);
        list.add(77);
        list.add(88);
        Integer integer = list.stream().max(Integer::compareTo).get();
        System.out.println("integer = " + integer);
    }

    /**
     * min:返回流中元素最小值
     */
    @Test
    public void testMin() {
        List<Integer> list = new ArrayList<>();
        list.add(11);
        list.add(22);
        list.add(33);
        list.add(44);
        list.add(55);
        list.add(66);
        list.add(77);
        list.add(88);
        Integer integer = list.stream().min(Integer::compareTo).get();
        System.out.println("integer = " + integer);
        list.stream().limit(1).limit(2).distinct().skip(3).filter(f -> f.equals(55)).forEach(System.out::println);
    }
}

總結

以上就是對於JDK1.8中Stream流式計算的一個簡單介紹,關於JDK1.8中的新特性,用法遠遠不止這些,這篇文章只作為一個簡單的入門使用,更深層次的理解請後續關注JDK1.8系列的文章。

Thinkingcao CSDN認證部落格專家 Java Spring Boot 架構
CSDN2019年度部落格之星、部落格專家,專注架構、Java、SpringBoot、SpringCloud、Spring、微服務、分散式等領域