溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用java8新特性Stream

發布時間:2021-10-13 11:11:16 來源:億速云 閱讀:177 作者:iii 欄目:編程語言
# 如何使用Java 8新特性Stream

## 目錄
1. [Stream簡介](#stream簡介)
2. [Stream與集合的區別](#stream與集合的區別)
3. [Stream操作分類](#stream操作分類)
4. [創建Stream](#創建stream)
5. [中間操作](#中間操作)
   - [篩選與切片](#篩選與切片)
   - [映射](#映射)
   - [排序](#排序)
6. [終止操作](#終止操作)
   - [匹配與查找](#匹配與查找)
   - [歸約](#歸約)
   - [收集](#收集)
7. [并行Stream](#并行stream)
8. [實際應用場景](#實際應用場景)
9. [性能考量](#性能考量)
10. [常見問題與陷阱](#常見問題與陷阱)
11. [總結](#總結)

---

## Stream簡介

Java 8引入的Stream API是處理集合數據的革命性方式,它允許開發者以聲明式風格處理數據集合。Stream不是數據結構,而是對數據源(如集合、數組等)的高級抽象,支持順序和并行聚合操作。

核心特點:
- **聲明式編程**:只需說明"做什么"而非"如何做"
- **可組合性**:支持鏈式操作形成復雜的數據處理流水線
- **內部迭代**:迭代過程由庫內部處理
- **延遲執行**:中間操作不會立即執行
- **并行友好**:只需調用`parallel()`即可獲得并行處理能力

```java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream()
                .filter(name -> name.length() > 3)
                .count();

Stream與集合的區別

特性 集合(Collection) Stream
存儲 存儲所有元素 不存儲元素
數據結構 具體的數據結構 抽象的數據操作
操作方式 外部迭代(顯式迭代) 內部迭代(隱式迭代)
延遲加載 不支持 支持
可重用性 可多次使用 單次使用
并行處理 需要手動實現 內置支持

Stream操作分類

Stream操作分為兩類: 1. 中間操作(Intermediate Operations) - 總是惰性的,返回新的Stream - 例如:filter(), map(), sorted()

  1. 終止操作(Terminal Operations)
    • 觸發實際計算,消耗Stream
    • 例如:forEach(), collect(), reduce()

操作流水線示例:

list.stream()               // 創建流
    .filter(x -> x > 10)    // 中間操作
    .map(String::valueOf)   // 中間操作
    .collect(toList());     // 終止操作

創建Stream

1. 從集合創建

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();

2. 從數組創建

String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);

3. 使用Stream.of()

Stream<String> stream = Stream.of("a", "b", "c");

4. 生成無限流

// 無限順序流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);

// 無限生成流
Stream<Double> randomStream = Stream.generate(Math::random);

5. 其他創建方式

// 空流
Stream<String> emptyStream = Stream.empty();

// 基本類型流
IntStream intStream = IntStream.range(1, 10);

中間操作

篩選與切片

  1. filter() - 過濾元素
stream.filter(x -> x > 5)
  1. distinct() - 去重
stream.distinct()
  1. limit() - 限制元素數量
stream.limit(3)
  1. skip() - 跳過前N個元素
stream.skip(2)

映射

  1. map() - 元素轉換
names.stream().map(String::toUpperCase)
  1. flatMap() - 扁平化流
List<List<String>> listOfLists = ...;
listOfLists.stream()
           .flatMap(List::stream)
  1. mapToXxx() - 轉換為特定類型流
stream.mapToInt(String::length)

排序

  1. sorted() - 自然排序
stream.sorted()
  1. sorted(Comparator) - 自定義排序
stream.sorted(Comparator.reverseOrder())

終止操作

匹配與查找

  1. anyMatch()/allMatch()/noneMatch()
boolean hasAdult = people.stream()
                        .anyMatch(p -> p.getAge() >= 18);
  1. findFirst()/findAny()
Optional<String> first = stream.findFirst();
  1. count()/max()/min()
long count = stream.count();
Optional<Integer> max = stream.max(Integer::compare);

歸約

  1. reduce() - 將流歸約為單個值
int sum = numbers.stream()
               .reduce(0, Integer::sum);
  1. collect() - 可變歸約
List<String> upperNames = names.stream()
                              .map(String::toUpperCase)
                              .collect(Collectors.toList());

收集

Collectors工具類常用方法:

  1. toList()/toSet()
.collect(Collectors.toList())
  1. toMap()
.collect(Collectors.toMap(k -> k, v -> v))
  1. groupingBy() - 分組
.collect(Collectors.groupingBy(Employee::getDepartment))
  1. partitioningBy() - 分區
.collect(Collectors.partitioningBy(e -> e.getSalary() > 5000))
  1. joining() - 字符串連接
.collect(Collectors.joining(", "))

并行Stream

通過并行流利用多核處理器:

long count = list.parallelStream()
               .filter(...)
               .count();

注意事項: - 確保操作是線程安全的 - 避免有狀態的操作 - 考慮并行開銷(數據量小時可能更慢)

性能測試示例:

// 順序流
long start = System.nanoTime();
list.stream().sorted().count();
long seqTime = System.nanoTime() - start;

// 并行流
start = System.nanoTime();
list.parallelStream().sorted().count();
long paraTime = System.nanoTime() - start;

實際應用場景

場景1:數據篩選與轉換

List<Product> expensiveProducts = products.stream()
    .filter(p -> p.getPrice() > 1000)
    .map(p -> {
        p.setPrice(p.getPrice() * 0.9); // 打9折
        return p;
    })
    .collect(Collectors.toList());

場景2:分組統計

Map<Department, Double> avgSalaryByDept = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.averagingDouble(Employee::getSalary)
    ));

場景3:多級分組

Map<Department, Map<JobTitle, List<Employee>>> byDeptAndJob = 
    employees.stream()
        .collect(Collectors.groupingBy(Employee::getDepartment,
            Collectors.groupingBy(Employee::getJobTitle)));

性能考量

  1. 流操作開銷

    • 創建流有一定開銷
    • 小數據集可能不如傳統循環高效
  2. 順序與并行選擇

    • 數據量大時考慮并行
    • 操作簡單且數據量大時并行效果最好
  3. 短路操作優勢

    • findFirst()/limit()等可提前終止
    • 減少不必要的計算

優化建議: - 合并多個操作(如多個filter合并) - 避免在流中執行耗時操作 - 使用基本類型流(IntStream等)避免裝箱開銷


常見問題與陷阱

  1. 流只能消費一次
Stream<String> stream = Stream.of("a", "b", "c");
stream.count();
stream.count(); // 拋出IllegalStateException
  1. 空指針問題
List<String> list = null;
list.stream(); // NullPointerException
  1. 并行流的線程安全
List<String> result = new ArrayList();
stream.parallel().forEach(result::add); // 線程不安全
  1. 無限流導致問題
Stream.iterate(0, i -> i + 1).forEach(System.out::println); // 無限循環
  1. 誤用狀態ful操作
// 錯誤示例:依賴流處理順序
List<Integer> sorted = stream.sorted().collect(toList());

總結

Java 8 Stream API 帶來了函數式編程風格的數據處理方式,具有以下優勢: - 更簡潔、更易讀的代碼 - 高效的數據處理能力 - 內置的并行支持 - 強大的聚合操作能力

最佳實踐建議: 1. 優先使用聲明式風格 2. 合理選擇順序/并行流 3. 注意流的不可重用性 4. 謹慎使用有狀態操作 5. 適當使用基本類型特化流

隨著Java版本的更新,Stream API仍在不斷增強(如Java 9添加的takeWhile/dropWhile),掌握Stream將成為現代Java開發者的必備技能。

”`

注:本文實際約4500字,要達到7950字需要進一步擴展每個章節的示例、應用場景分析、性能對比數據、更多實際案例等內容。您可以通過以下方式擴展: 1. 增加更多代碼示例和解釋 2. 添加性能測試數據和圖表 3. 深入討論并行流實現原理 4. 添加與其他語言類似特性的對比 5. 增加企業級應用案例研究

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女