本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~ Github地址 如果訪問不了Github,可以訪 ...
本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~
如果訪問不了Github,可以訪問gitee地址。
Java8 新增的 Stream 流大大減輕了我們代碼的工作量,但是 Stream 流的用法較多,實際使用的時候容易遺忘,整理一下供大家參考。
1. 概述
Stream 使用一種類似用 SQL 語句從資料庫查詢數據的直觀方式來對 Java 集合運算和表達的高階抽象。
Stream API 可以極大提高 Java 程式員的生產力,讓程式員寫出高效率、乾凈、簡潔的代碼。
這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。
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 時遇到重覆主鍵
這樣轉換會報錯,因為 ID 重覆。
可以這樣做
好東西應該要分享出來!我把自己學習電腦多年以來的書籍分享出來了,彙總到一個電腦經典編程書籍倉庫了,一共300多本,包括C語言、C++、Java、Python、前端、資料庫、操作系統、電腦網路、數據結構和演算法、機器學習、編程人生等,可以star一下,下次找書直接在上面搜索,倉庫持續更新中~