1. 程式人生 > >Stream相關API學習使用記錄--(一)

Stream相關API學習使用記錄--(一)

一、前言

在以前的工作中,業務中很多時候是需要迴圈來獲取某一個列表中的一些資料,比如獲取某一個值做業務邏輯的判斷,或者獲取其中一部分的資料,如使用狀態的標誌位等等,這個時候可能很多時候都是使用簡單的for迴圈、Foreach迴圈或者迭代器等方式,很多時候為了處理業務都是需要迴圈巢狀迴圈的。但是在Java8中為集合的相關處理提供了一個更強大的工具,那麼就是Stream,在瀏覽程式碼的時候看見了其他人的書寫,感覺很驚奇(此時自己也很無語,Java8出來這麼久了,自己好像好沒有意識到它到底添加了那些新的內容,有什麼新的特性,簡化了那些操作等等),所以自己就對這個東西充滿了好奇。

二、 Stream的基礎簡介

2.1、stream是什麼

它是Java8 API新增的一個新的抽象流,它把要處理的元素看做一種流,流在管道中傳輸,並且可以在管道的節點上進行處理,例如排序,篩選和聚合等操作,可以讓人以一種宣告的方式來處理資料。
元素流在管道中經過中間操作(intermediate operation)處理,最後由最終操作(terminal operation)得到前面的處理結果。


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

2.2、特性

stream是一個來自資料來源的元素佇列並支援聚合操作:
(1)元素是特定的元素,形成一個佇列,但是stream不會儲存元素,而是按需計算
(2)資料來源可以是集合、陣列、I/Ochannel等
(3)集合操作類似鏈式的SQL,如filter、map、reduce、find、match、sortde等

2.3、流生成方式

2.3.1、序列流

使用stream方式,為集合建立序列流

2.3.2、並行流

使用parallelStream 為集合建立並行流

三、管道節點

3.1、ForEach

Stream提供了新的方法來迭代流中的每一個數據

public class
StreamDemoTest { private final static Integer MAX_CIRCLE = 100; public static void main(String[] args) { List<Integer> strList = new ArrayList<>(); Map<Integer, String> integerMap = new HashMap<>(); for (int i = 0; i < MAX_CIRCLE; i++) { strList.add(i); integerMap.put(i, i+"e"); } strList.stream().forEach(s -> System.out.println(s)); } }

3.2、map

map方法用於對映每個元素到對應的結果

public class StreamDemoTest {

    private final static Integer MAX_CIRCLE = 100;
    public static void main(String[] args) {
        List<Integer> strList = new ArrayList<>();
        Map<Integer, String> integerMap = new HashMap<>();
        for (int i = 0; i < MAX_CIRCLE; i++) {
            strList.add(i);
            integerMap.put(i, i+"e");
        }
         //strList.stream().forEach(s -> System.out.println(s));
        List<Integer> integerList = strList.stream().map(i -> i * i).collect(Collectors.toList());
        integerList.stream().forEach(s -> System.out.println(s));

    }
}

3.3、filter

filter用於通過設定的條件過濾出元素

List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 獲取空字串的數量
        long count = stringList.stream().filter(string ->string!="abc").count();
    //獲取不是abc和空的字串
        List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").collect(Collectors.toList());

3.4、limit

用於獲取指定數量的流

List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 獲取空字串的數量
        long count = stringList.stream().filter(string ->string!="abc").count();
        //限定獲取過濾條件後的數量
        List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").limit(3).collect(Collectors.toList());
        list.stream().forEach(s-> System.out.println(s));

limit的位置可以在filter前面或者後面,只是表示的含義不一樣而已。

3.4、sorted

sorted用於對流進行排序

 
public static void main(String[] args) {
        List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        //自然排序
        System.out.println("自然排序");
        strList.stream().sorted().forEach(s -> System.out.println(s));

        System.out.println("倒序排序");
        strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));
    }

輸出結果已經按照要求進行了排序,預設的是升序排列了,如果想簡單的倒序排序,可以使用 Stream<T> sorted(Comparator<? super T> comparator)方法,裡面採用Comparator.reverseOrder()進行倒序排序。
如果是自定義的其他的型別,怎麼進行排序那?

下面是自定義的一個使用者資訊的簡單實體

class User {
    /**
     * 姓名
     **/
    private String userName;
    /**
     * 英文名稱
     **/
    private String englishName;
    /**
     * 年齡
     **/
    private int age;
    /**
     * 住址
     **/
    private String address;
    /**
     * 電話
     **/
    private String tel;

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

    public User(String userName, String englishName, int age, String address, String tel) {
        this.userName = userName;
        this.englishName = englishName;
        this.age = age;
        this.address = address;
        this.tel = tel;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEnglishName() {
        return englishName;
    }

    public void setEnglishName(String englishName) {
        this.englishName = englishName;
    }

    public int getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

@Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", englishName='" + englishName + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                '}';
    }
}
demo示例
1
public static void main(String[] args) { 2 /* List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 3 //自然排序 4 System.out.println("自然排序"); 5 strList.stream().sorted().forEach(s -> System.out.println(s)); 6 7 System.out.println("倒序排序"); 8 strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));*/ 9 10 List<User> userList = new ArrayList<>(); 11 User user = new User("Angle", "B", 10); 12 userList.add(user); 13 user = new User("Heni", "G", 39); 14 userList.add(user); 15 user = new User("Eson", "F", 6); 16 userList.add(user); 17 user = new User("Cily", "D", 2); 18 userList.add(user); 19 user = new User("Cily", "G", 6); 20 userList.add(user); 21 System.out.println("正常輸出"); 22 userList.stream().forEach(s-> System.out.println(s.toString())); 23 24 System.out.println("按照名稱預設升序排列"); 25 userList.stream().sorted(Comparator.comparing(User::getUserName)).forEach(s -> System.out.println(s)); 26 27 System.out.println("按照名稱進行倒序排列"); 28 userList.stream().sorted(Comparator.comparing(User::getUserName).reversed()).forEach(s -> System.out.println(s)); 29 30 System.out.println("多元素排列"); 31 userList.stream().sorted(Comparator.comparing(User::getUserName).thenComparing(User::getAge).reversed()).forEach(s -> System.out.println(s)); 32 }

輸出結果:

正常輸出
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
按照名稱預設升序排列
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
按照名稱進行倒序排列
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
多元素排列
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}

可以看出來,整個排序是相當的簡單了,不需要自己的類繼承comparable,也不需要自己擴充套件排序comparator了。
對於map型別格式的資料。可以對鍵排序或者值排序

 1 public static void main(String[] args) {
 2         Map<String, String> map = new LinkedHashMap<String, String>();
 3         map.put("12", "ddd");
 4         map.put("23", "eee");
 5         map.put("34", "ddw");
 6         map.put("21", "ecc");
 7 
 8         System.out.println("根據值排序");
 9         map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(e -> {
10             String key = e.getKey();
11             String value = e.getValue();
12             System.out.println("鍵值"+key+"值"+value);
13         });
14         System.out.println("根據鍵排序");
15         map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(e -> {
16             //System.out.println(e.toString());
17             String key = e.getKey();
18             String value = e.getValue();
19             System.out.println("鍵值"+key+"值"+value);
20         });
21 }

輸出的結果:

根據值排序
鍵值12值ddd
鍵值34值ddw
鍵值21值ecc
鍵值23值eee
根據鍵排序
鍵值12值ddd
鍵值21值ecc
鍵值23值eee
鍵值34值ddw

綜合看下來,使用對應的Stream比使用平常簡單的迴圈而言程式碼量少了很多。