天天看點

Java Stream常見用法彙總,開發效率大幅提升

作者:肚臍眼女孩

Java8 新增的 Stream 流大大減輕了我們代碼的工作量,但是 Stream 流的用法較多,實際使用的時候容易遺忘,整理一下供大家參考。

1. 概述

Stream 使用一種類似用 SQL 語句從資料庫查詢資料的直覺方式來對 Java 集合運算和表達的高階抽象。

Stream API 可以極大提高 Java 程式員的生産力,讓程式員寫出高效率、幹淨、簡潔的代碼。

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

Java Stream常見用法彙總,開發效率大幅提升

2. 建立

2.1 集合自帶 Stream 流方法

List<String> list = new ArrayList<>();
// 建立一個順序流
Stream<String> stream = list.stream();
// 建立一個并行流
Stream<String> parallelStream = list.parallelStream();
           

2.1 通過 Array 數組建立

int[] array = {1,2,3,4,5};
IntStream stream = Arrays.stream(array);
           

2.3 使用 Stream 的靜态方法建立

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> stream = Stream.iterate(0, (x) -> x + 3).limit(3); // 輸出 0,3,6

Stream<String> stream = Stream.generate(() -> "Hello").limit(3); // 輸出 Hello,Hello,Hello
Stream<Double> stream = Stream.generate(Math::random).limit(3); // 輸出3個随機數
           

2.3 數值流

// 生成有限的常量流
IntStream intStream = IntStream.range(1, 3); // 輸出 1,2
IntStream intStream = IntStream.rangeClosed(1, 3); // 輸出 1,2,3
// 生成一個等差數列
IntStream.iterate(1, i -> i + 3).limit(5).forEach(System.out::println); // 輸出 1,4,7,10,13
// 生成無限常量資料流
IntStream generate = IntStream.generate(() -> 10).limit(3); // 輸出 10,10,10
           

另外還有 LongStream、DoubleStream 都有這幾個方法。

3. 使用

初始化一些資料,示例中使用。

public class Demo {
    class User{
        // 姓名
        private String name;

        // 年齡
        private Integer age;
    }

    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Tom", 1));
        users.add(new User("Jerry", 2));
    }
}
           

3.1 周遊 forEach

// 循環輸出user對象
users.stream().forEach(user -> System.out.println(user));
           

3.2 查找 find

// 取出第一個對象
User user = users.stream().findFirst().orElse(null); // 輸出 {"age":1,"name":"Tom"}
// 随機取出任意一個對象
User user = users.stream().findAny().orElse(null);
           

3.3 比對 match

// 判斷是否存在name是Tom的使用者
boolean existTom = users.stream().anyMatch(user -> "Tom".equals(user.getName()));
// 判斷所有使用者的年齡是否都小于5
boolean checkAge = users.stream().allMatch(user -> user.getAge() < 5);
           

3.4 篩選 filter

// 篩選name是Tom的使用者
users.stream()
        .filter(user -> "Tom".equals(user.name))
        .forEach(System.out::println); // 輸出 {"age":1,"name":"Tom"}
           

3.5 映射 map/flatMap

// 列印users裡的name
users.stream().map(User::getName).forEach(System.out::println); // 輸出 Tom Jerry
// List<List<User>> 轉 List<User>
List<List<User>> userList = new ArrayList<>();
List<User> users = userList.stream().flatMap(Collection::stream).collect(Collectors.toList());
           

3.6 歸約 reduce

// 求使用者年齡之和
Integer sum = users.stream().map(User::getAge).reduce(Integer::sum).orElse(0);
// 求使用者年齡的乘積
Integer product = users.stream().map(User::getAge).reduce((x, y) -> x * y).orElse(0);
           

3.7 排序 sorted

// 按年齡倒序排
List<User> collect = users.stream()
        .sorted(Comparator.comparing(User::getAge).reversed())
        .collect(Collectors.toList());

//多屬性排序
List<Person> result = persons.stream()
                .sorted(Comparator.comparing((Person p) -> p.getNamePinyin())
                        .thenComparing(Person::getAge)).collect(Collectors.toList());
           

3.8 收集 collect

// list轉換成map
Map<Integer, User> map = users.stream()
        .collect(Collectors.toMap(User::getAge, Function.identity()));

// 按年齡分組
Map<Integer, List<User>> userMap = users.stream().collect(Collectors.groupingBy(User::getAge));

// 求平均年齡
Double ageAvg = users.stream().collect(Collectors.averagingInt(User::getAge)); // 輸出 1.5

// 求年齡之和
Integer ageSum = users.stream().collect(Collectors.summingInt(User::getAge));

// 求年齡最大的使用者
User user = users.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge))).orElse(null);

// 把使用者姓名拼接成逗号分隔的字元串輸出
String names = users.stream().map(User::getName).collect(Collectors.joining(",")); // 輸出 Tom,Jerry
           

3.9 List 轉換成 Map 時遇到重複主鍵

Java Stream常見用法彙總,開發效率大幅提升

這樣轉換會報錯,因為 ID 重複。

Java Stream常見用法彙總,開發效率大幅提升

可以這樣做

Java Stream常見用法彙總,開發效率大幅提升

繼續閱讀