天天看點

Java8中Stream的常用方法

前言

這篇文章簡單總結一下Stream中的常用方法,,當然一般都是和Lambda配合着使用的。

對Lambda不熟悉的同學,可以參考這篇進行入門​​對Lambda的了解​​,Lambda真是越用越爽

如果剛剛入門Lambda,但對Consumer、Supplier、Predicate與Function不怎麼熟悉的同學,可以參考這篇文章​​快速了解Consumer、Supplier、Predicate與Function​​

如果已經對Lambda很熟悉的同學,但對其執行原理不太懂的同學,可以參考我的這篇文章​​Lambda執行原理​​

先給出一個示例

下面有五個學生,放入到集合中

@Data
       @AllArgsConstructor
       class Student {
           private String name;
           private Integer age;
       }      


        Student a = new Student("a", 20);
        Student b = new Student("b", 18);
        Student c = new Student("c", 22);
        Student d = new Student("d", 19);
        Student e = new Student("e", 18);
        List<Student> list = new ArrayList<>();
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);      

在日常開發中,可能有以下的需求:

一、周遊該集合

list.forEach(System.out::println);      

forEach接受一個Consumer表達式

二、取出學生姓名

List<String> nameList = list.stream()
                .map(Student::getName)
                .collect(Collectors.toList());      

stream可以将一種形式的流轉化為另外一種形式的流,上面的代碼,是将包含整個學生對象的流,轉化成了單獨包含姓名的流,最後使用collect方法,将流收集起來。

三、取出年齡大于19歲的學生

List<Student> studentList = list.stream()
                .filter(s -> s.getAge() > 19)
                .collect(Collectors.toList());      

filter接收一個Predicate表達式,将會在流中丢棄不符合表達式的學生對象。

四、取出不重複的學生年齡

List<Integer> ageDistinctList = list.stream()
                .map(Student::getAge)
                .distinct()
                .collect(Collectors.toList());      

和mysql的去重關鍵字一樣,都是使用distinct

五、全比對、任意比對、都不比對

需求1:是否所有學生的年齡都在18歲以上(全比對)

boolean flag = list.stream()
                .map(Student::getAge)
                .allMatch(i -> i > 18);      

需求2:是否有學生的年齡大于21歲(任意比對)

boolean flag = list.stream()
                .map(Student::getAge)
                .anyMatch(i -> i > 21);      

需求3:是否所有學生的年齡都不大于22歲(都不比對)

boolean flag = list.stream()
                .map(Student::getAge)
                .noneMatch(i -> i > 22);      

六、排序

需求,按照學生的年齡進行排序

list.stream()
                .sorted(Comparator.comparingInt(Student::getAge))
                .forEach(System.out::println);      

輸出:

Java8中Stream的常用方法

預設是按照年齡進行升序輸出,當然也可以降序輸出,隻要加上.reversed即可,如下圖

list.stream()
                .sorted(Comparator.comparingInt(Student::getAge).reversed())
                .forEach(System.out::println);      

如果先按照年齡排序,再按照姓名進行排序,則可以寫成:

list.stream()
                .sorted(Comparator.comparingInt(Student::getAge).thenComparing(Student::getName))
                .forEach(System.out::println);      

七、分頁

需求:目前頁是第2頁,每頁顯示3條

list.stream()
                .sorted(Comparator.comparingInt(Student::getAge))
                .skip((2 - 1) * 3) //(目前頁-1)*每頁顯示條數
                .limit(3)          //每頁顯示條數
                .forEach(System.out::println);      

首先按照年齡進行排序,然後跳過上一頁的資料,取出之後的limit條資料。

八、分組

需求:照年齡進行分組

Map<Integer, List<Student>> group = list.stream().collect(Collectors.groupingBy(Student::getAge));
        group.forEach((k, v) -> System.out.println("k:" + k + ",v:" + v.toString()));      

輸出:

Java8中Stream的常用方法

九、字元串拼接

需求:輸出學生姓名用逗号隔開的字元串

String str = list.stream().map(Student::getName).collect(Collectors.joining(","));
        System.out.println(str);      

輸出:

Java8中Stream的常用方法

十、數學運算

需求1:求學生年齡的總和

int sum = list.stream().mapToInt(Student::getAge).sum();
        System.out.println(sum);      

需求2:求學生年齡的平均數

double average = list.stream()
                .mapToInt(Student::getAge)
                .average()
                .orElse(0.0);
        System.out.println(average);      

注意,average()傳回的是一個OptionalDouble,為了防止集合中沒有元素時,我們必須使用orElse指定一個預設值。

同理,求最大值使用max,最小值使用min,都需要指定預設值。

持續補充案例....