天天看點

Java 8 Stream API詳解Java 8 Stream API詳解

版權聲明:本文為部落客chszs的原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/chszs/article/details/47038607

Java 8 Stream API詳解

一、Stream API介紹

Java 8引入了全新的Stream API,此Stream與Java I/O包裡的InputStream和OutputStream是完全不同的概念,它不同于StAX對XML解析的Stream,也不同于Amazon Kinesis對大資料實時處理的Stream。Stream API更像具有Iterable的集合類,但行為和集合類又有所不同,它是對集合對象功能的增強,專注于對集合對象進行各種非常便捷、高效的聚合操作或大批量資料操作。

Stream API引入的目的在于彌補Java函數式程式設計的缺陷。對于很多支援函數式程式設計的語言,map()、reduce()基本上都内置到語言的标準庫中了,不過,Java 8的Stream API總體來講仍然是非常完善和強大,足以用很少的代碼完成許多複雜的功能。

Java 8的Stream API充分利用Lambda表達式的特性,極大的提高程式設計效率和程式可讀性。同時它提供串行和并行兩種模式進行彙聚操作,并發模式能夠充分利用多核處理器的優勢,使用fork/join并行方式來拆分任務和加速處理過程。通常編寫并行代碼很難而且容易出錯,但使用Stream API無需編寫一行多線程的代碼,就可以很友善地寫出高性能的并發程式。

在Stream API中,一個流基本上代表一個元素序列,Stream API提供了豐富的操作函數來計算這些元素。以前我們在開發業務應用時,通常很多操作的實作是這樣做的:我們使用循環對集合做周遊,針對集合中的元素實作各種操作,定義各種變量來實作目的,這樣我們就得到了一大堆醜陋的順序代碼。

如果我們使用Stream API做同樣的事情,使用Lambda表達式和其它函數進行抽象,可以使得代碼更易于了解、更為幹淨。有了這些抽象,還可以做一些優化,比如實作并行等。

二、Stream API執行個體

1. 使用IntStream移除正常的循環

比如在控制台輸出0~9的例子:

注意需import java.util.stream.IntStream;

IntStream.range(0, 10).forEach(value -> System.out.println(value));
           

2. 計算清單中的元素數

注意需

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

List<Integer> list = IntStream.range(1, 100).boxed().collect(Collectors.toList());
System.out.println(list.stream().count());
           

3. 計算清單中元素的平均數

Double avarage = list.stream().collect(Collectors.averagingInt(item -> item));
           

4. 對清單元素進行統計

List<Integer> list = IntStream.range(1, 100).boxed().collect(Collectors.toList());
IntSummaryStatistics iss = list.stream().collect(Collectors.summarizingInt(value -> value));
System.out.println(iss);
           

輸出結果:

IntSummaryStatistics{count=99, sum=4950, min=1, average=50.000000, max=99}
           

5. 根據List建立Map

List<Integer> list = IntStream.range(1, 100).boxed().collect(Collectors.toList());
Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(p -> p, q->q*3));
System.out.println(map);
           
{1=3, 2=6, 3=9, 4=12, 5=15, 6=18, 7=21, 8=24, 9=27, 10=30, 11=33, 12=36, 13=39, 14=42, 15=45, 16=48, 17=51, 18=54, 19=57, 20=60, 21=63, 22=66, 23=69, 24=72, 25=75, 26=78, 27=81, 28=84, 29=87, 30=90, 31=93, 32=96, 33=99, 34=102, 35=105, 36=108, 37=111, 38=114, 39=117, 40=120, 41=123, 42=126, 43=129, 44=132, 45=135, 46=138, 47=141, 48=144, 49=147, 50=150, 51=153, 52=156, 53=159, 54=162, 55=165, 56=168, 57=171, 58=174, 59=177, 60=180, 61=183, 62=186, 63=189, 64=192, 65=195, 66=198, 67=201, 68=204, 69=207, 70=210, 71=213, 72=216, 73=219, 74=222, 75=225, 76=228, 77=231, 78=234, 79=237, 80=240, 81=243, 82=246, 83=249, 84=252, 85=255, 86=258, 87=261, 88=264, 89=267, 90=270, 91=273, 92=276, 93=279, 94=282, 95=285, 96=288, 97=291, 98=294, 99=297}
           

6. 求清單元素的最大數

List<Integer> list = new Random().ints(-100,100).limit(250).boxed().collect(Collectors.toList());
Optional<Integer> max = list.stream().reduce(Math::max);
max.ifPresent(value -> System.out.println(value));
           

7. 從一堆姓名清單中找出以字母“C”開頭的姓名

​String[] names = { "Fred Edwards", "Anna Cox", "Deborah Patterson", "Ruth Torres", "Shawn Powell",
                "Rose Thompson", "Rachel Barnes", "Eugene Ramirez", "Earl Flores", "Janice Reed", "Sarah Miller",
                "Patricia Kelly", "Carl Hall", "Craig Wright", "Martha Phillips", "Thomas Howard", "Steve Martinez",
                "Diana Bailey", "Kathleen Hughes", "Russell Anderson", "Theresa Perry" };
List<String> ls = Arrays.asList(names).stream().filter(s -> s.startsWith("C")).collect(Collectors.toList());
System.out.println(ls.toString());
           

8. 把所有的姓名大寫、排序,再輸出

String[] names = { "Fred Edwards", "Anna Cox", "Deborah Patterson", "Ruth Torres", "Shawn Powell",
                "Rose Thompson", "Rachel Barnes", "Eugene Ramirez", "Earl Flores", "Janice Reed", "Sarah Miller",
                "Patricia Kelly", "Carl Hall", "Craig Wright", "Martha Phillips", "Thomas Howard", "Steve Martinez",
                "Diana Bailey", "Kathleen Hughes", "Russell Anderson", "Theresa Perry" };
Arrays.asList(names)
         .stream()
         .map(String::toUpperCase)
         .sorted().forEach(System.out::println);
           

三、更複雜的例子

1. 建立一個Person類

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

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

    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 String toString() {
        return name;
    }
}
           

2. 根據年齡對Person進行分組

Map<Integer, List<Person>> collect = persons.stream().collect(Collectors.groupingBy(Person::getAge));
           

3. 對所有Person求平均年齡

Double collect = persons.stream().collect(Collectors.averagingInt(Person::getAge));