Java8的StreamAPI常用方法總結

Java8新增的Stream + Lambda = !!!起飛,誰用誰知道!

什麼是Stream?

Stream將要處理的元素集合看作一種流,在流的過程中,藉助Stream API對流中的元素進行操作,比如:篩選、排序、聚合等。

Stream可以由數組或集合創建,對流的操作分爲兩種:

  1. 中間操作,每次返回一個新的流,可以有多個。
  2. 終端操作,每個流只能進行一次終端操作,終端操作結束後流無法再次使用。終端操作會產生一個新的集合或值。

另外,Stream有幾個特性:

  1. stream不存儲數據,而是按照特定的規則對數據進行計算,一般會輸出結果。
  2. stream不會改變數據源,通常情況下會產生一個新的集合或一個值。

Stream的創建

public class BuildStream {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3);
        // 通過集合的stream()方法創建順序流
        Stream<Integer> stream1 = list.stream();

        // 通過集合的parallelStream()方法創建順序流
        Stream<Integer> parallelStream1 = list.parallelStream();

        // 通過parallel()將順序流轉化爲並行流
        Stream<Integer> parallelStream2 = list.stream().parallel();

        int[] arr = {1, 2, 3};
        // 通過數組創建流
        IntStream stream2 = Arrays.stream(arr);

        // 通過Stream的靜態方法創建流
        Stream<Integer> stream3 = Stream.of(1, 2, 3);
        Stream<Integer> stream4 = Stream.iterate(1, x -> x + 1).limit(3);

        stream1.forEach(x -> System.out.print(x + " "));
        System.out.println(); // 1 2 3

        parallelStream1.forEach(x -> System.out.print(x + " "));
        System.out.println(); // 隨機
    }
}
  • stream是順序流,由主線程按順序對流執行操作。
  • parallelStream是並行流,內部以多線程並行執行的方式對流進行操作,但前提流中的數據處理沒有順序要求。並行流能充分利用cpu優勢,在數據量足夠大的時候,加快處理速度。

測試API

新建測試數據

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Book {

    Long id;
    String title;
    String author;
    Integer pageCount;
    Double price;
}

public class TestStream {

    List<Book> bookList = new ArrayList<>();

    @Before
    public void init() {
        bookList.add(Book.builder().author("天喬巴夏").id(1L).title("Java-Spring").pageCount(100).price(50d).build());
        bookList.add(Book.builder().author("summerday").id(2L).title("Java-SpringBoot").pageCount(200).price(100d).build());
        bookList.add(Book.builder().author("hyh").id(3L).title("mysql").pageCount(500).price(150d).build());
        bookList.add(Book.builder().author("tqbx").id(4L).title("Linux").pageCount(30).price(10d).build());
    }
}

findFirst、findAny

        // 匹配第一個
        Optional<Book> first = bookList.stream().filter(book -> book.getPageCount() > 100).findFirst();
        first.ifPresent(book -> System.out.println("匹配第一個值 : " + book));

        // 匹配任意
        Optional<Book> any = bookList.parallelStream().filter(book -> book.getPageCount() > 100).findAny();
        any.ifPresent(book -> System.out.println("匹配任意的值 : " + book));

anyMatch、noneMatch

        // 是否包含符合條件的書
        boolean anyMatch = bookList.stream().anyMatch(book -> book.getPageCount() > 100);
        System.out.println("是否存在頁數大於100的書 : " + anyMatch);

        // 檢查是否有名字長度大於5 的
        boolean noneMatch = bookList.stream().noneMatch(book -> (book.getTitle().length() > 5));
        System.out.println("不存在title長度大於5的書 : " + noneMatch);

filter

        // 找到所有id爲奇數的書,列出他們的書名到list中
        List<String> titleList = bookList.stream()
                .filter(book -> book.getId() % 2 == 1)
                .map(Book::getTitle)
                .collect(Collectors.toList());
        System.out.println(titleList);

max、count

        // 獲取頁數最多的書
        Optional<Book> max = bookList.stream().max(Comparator.comparingInt(Book::getPageCount));
        max.ifPresent(book -> System.out.println("頁數最多的書 : " + book));
        // 計算mysql書籍有幾本
        long count = bookList.stream().filter(book -> book.getTitle().contains("mysql")).count();
        System.out.println("mysql書籍的本數 : " + count);

peek、map

        // 將所有的書的價格調高100並輸出調高以後的書單
        List<Book> result = bookList.stream().peek(book -> book.setPrice(book.getPrice() + 100))
                .collect(Collectors.toList());
        result.forEach(System.out::println);
        // 獲取所有書的id列表
        List<Long> ids = bookList.stream().map(Book::getId).collect(Collectors.toList());
        System.out.println(ids);

reduce

        // 求所有書籍的頁數之和
        Integer totalPageCount = bookList.stream().reduce(0, (s, book) -> s += book.getPageCount(), Integer::sum);
        System.out.println("所有書籍的頁數之和 : " + totalPageCount);

collect

        // 將所有書籍存入 author -> title 的map中
        Map<String, String> map = bookList.stream().collect(Collectors.toMap(Book::getAuthor, Book::getTitle));
        // 取出所有id爲偶數的書,存入list
        List<Book> list = bookList.stream().filter(book -> book.getId() % 2 == 0).collect(Collectors.toList());
        // 取出所有標題長度大於5的書,存入list
        Set<Book> set = bookList.stream().filter(book -> book.getTitle().length() > 5).collect(Collectors.toSet());

count、averaging、summarizing、max、sum

        // 統計書籍總數
        Long bookCount = bookList.stream().filter(book -> "天喬巴夏".equals(book.getAuthor())).count();

        // 求平均價格
        Double average = bookList.stream().collect(Collectors.averagingDouble(Book::getPrice));

        // 求最貴价格
        Optional<Integer> max = bookList.stream().map(Book::getPageCount).max(Double::compare);

        // 求價格之和
        Integer priceCount = bookList.stream().mapToInt(Book::getPageCount).sum();

        // 一次性統計所有信息
        DoubleSummaryStatistics c = bookList.stream().collect(Collectors.summarizingDouble(Book::getPrice));

group

        // 按書的價格是否高於100分組
        Map<Boolean, List<Book>> part = bookList.stream().collect(Collectors.partitioningBy(book -> book.getPrice() > 100));

        for (Map.Entry<Boolean, List<Book>> entry : part.entrySet()) {
            if (entry.getKey().equals(Boolean.TRUE)) {
                System.out.println("price > 100 ==> " + entry.getValue());
            } else {
                System.out.println("price <= 100 <== " + entry.getValue());
            }
        }

        // 按頁數分組
        Map<Integer, List<Book>> group = bookList.stream().collect(Collectors.groupingBy(Book::getPageCount));
        System.out.println(group);

join

        // 獲取所有書名
        String titles = bookList.stream().map(Book::getTitle).collect(Collectors.joining(","));
        System.out.println("所有書名 : " + titles);

sort

        // 按價格升序
        List<Book> sortListByPrice = bookList.stream().sorted(Comparator.comparing(Book::getPrice)).collect(Collectors.toList());
        System.out.println(sortListByPrice);
        // 按價格降序
        List<Book> sortListByPriceReversed = bookList.stream().sorted(Comparator.comparing(Book::getPrice).reversed()).collect(Collectors.toList());
        System.out.println(sortListByPriceReversed);

        // 先價格再頁數
        List<Book> sortListByPriceAndPageCount = bookList.stream().sorted(Comparator.comparing(Book::getPrice)
                .thenComparing(Book::getPageCount)).collect(Collectors.toList());
        System.out.println(sortListByPriceAndPageCount);

distinct、concat、limit、skip

        Stream<Integer> stream1 = Stream.of(1, 2, 2, 3, 4);
        Stream<Integer> stream2 = Stream.of(2, 3, 4, 5, 5);
        // 合併
        List<Integer> concatList = Stream.concat(stream1, stream2).collect(Collectors.toList());
        System.out.println(concatList);

        // 去重
        List<Integer> distinctList = concatList.stream().distinct().collect(Collectors.toList());
        System.out.println(distinctList);

        // 限制
        List<Integer> limitList = distinctList.stream().limit(3).collect(Collectors.toList());
        System.out.println(limitList);

        // 跳過
        List<Integer> skipList = limitList.stream().skip(1).collect(Collectors.toList());
        System.out.println(skipList);

        // 迭代
        List<Integer> iterateList = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
        System.out.println(iterateList);

        // 生成
        List<Integer> generateList = Stream.generate(() -> new Random().nextInt()).limit(5).collect(Collectors.toList());
        System.out.println(generateList);

參考閱讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章