Lambda 函數和 peek 操作是 Java 8 Stream API 中非常有用的特性,下面我將介紹它們的使用案例。
Lambda 函數使用案例
Lambda 表達式是 Java 8 引入的一種簡潔的匿名函數表示方式。
集合操作
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用 Lambda 表達式排序
Collections.sort(names, (a, b) -> a.compareTo(b));// 使用 Lambda 表達式遍歷
names.forEach(name -> System.out.println(name));// 使用方法引用
names.forEach(System.out::println);
過濾和映射
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);// 過濾偶數
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());// 平方映射
List<Integer> squares = numbers.stream().map(n -> n * n).collect(Collectors.toList());
peek 操作使用案例
peek() 是 Stream API 中的一個中間操作,主要用于調試或觀察流中的元素而不改變它們。
List<String> result = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("Filtered value: " + e)).map(String::toUpperCase).peek(e -> System.out.println("Mapped value: " + e)).collect(Collectors.toList());
調試流操作
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List result = numbers.stream()
.peek(x -> System.out.println("原始: " + x))
.map(x -> x * 2)
.peek(x -> System.out.println("乘2后: " + x))
.filter(x -> x > 5)
.peek(x -> System.out.println("過濾后: " + x))
.collect(Collectors.toList());
修改對象狀態
List<User> users = getUsers();List<User> updatedUsers = users.stream().peek(user -> {if (user.getAge() > 30) {user.setGroup("Senior");}}).collect(Collectors.toList());
結合使用 Lambda 和 peek 的實用案例
案例1:日志調試
List<String> transactions = getTransactions();List<String> validTransactions = transactions.stream().filter(t -> t.startsWith("TX")) // Lambda 過濾.peek(t -> System.out.println("有效交易ID: " + t)) // 調試日志.map(t -> t.toUpperCase()) // Lambda 轉換.collect(Collectors.toList());
案例2:性能監控
List<Data> bigData = getData();long start = System.currentTimeMillis();List<Data> processed = bigData.stream().peek(d -> {if (System.currentTimeMillis() - start > 1000) {System.out.println("處理超時警告");}}).map(d -> processData(d)) // 假設processData是一個處理方法.collect(Collectors.toList());
案例3:多步驟處理
List<Product> products = getProducts();List<Product> discountedProducts = products.stream().peek(p -> System.out.println("原始價格: " + p.getPrice())).filter(p -> p.getPrice() > 100) // 只處理高價商品.peek(p -> p.setPrice(p.getPrice() * 0.9)) // 打9折.peek(p -> System.out.println("折扣后價格: " + p.getPrice())).collect(Collectors.toList());
注意事項
peek() 是一個中間操作,如果沒有終止操作,它不會執行
不要濫用 peek() 來修改狀態,這可能導致不可預期的行為
生產環境中應謹慎使用 peek() 進行日志記錄,可能影響性能
Lambda 表達式應保持簡潔,復雜邏輯應考慮使用方法引用或單獨的方法
Lambda 和 peek 的組合為 Java 流式編程提供了強大的調試和觀察能力,同時保持了代碼的簡潔性。
Java Stream API 常用操作詳解
下面我將詳細介紹 Java Stream API 中的 peek, filter, map, limit, skip, collect 和 distinct 等常用操作,并提供使用示例。
- peek() - 流元素操作(調試用)
peek() 是一個中間操作,用于觀察流中的元素而不改變它們,主要用于調試。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> result = names.stream().peek(name -> System.out.println("原始名字: " + name)).map(String::toUpperCase).peek(name -> System.out.println("轉換后: " + name)).collect(Collectors.toList());
- filter() - 過濾
filter() 根據條件過濾流中的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 過濾偶數
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());// 過濾長度大于3的字符串
List<String> longNames = names.stream().filter(name -> name.length() > 3).collect(Collectors.toList());
- map() - 映射
map() 將流中的每個元素轉換為另一個形式。
// 將字符串轉換為大寫
List<String> upperCaseNames = names.stream().map(String::toUpperCase).collect(Collectors.toList());// 提取對象屬性
List<Integer> nameLengths = names.stream().map(String::length).collect(Collectors.toList());// 復雜映射
List<Employee> employees = getEmployees();
List<String> employeeNames = employees.stream().map(Employee::getName).collect(Collectors.toList());
- limit() - 截斷
limit() 限制流中元素的數量。
// 只取前3個元素
List<Integer> firstThree = numbers.stream().limit(3).collect(Collectors.toList());// 結合其他操作
List<String> result = names.stream().filter(name -> name.length() > 3).limit(2).collect(Collectors.toList());
- skip() - 跳過
skip() 跳過流中的前N個元素。
// 跳過前2個元素
List<Integer> skipped = numbers.stream().skip(2).collect(Collectors.toList());// 分頁實現
int pageSize = 5;
int pageNumber = 2; // 第2頁
List<String> page = names.stream().skip((pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
- collect() - 收集
collect() 是一個終止操作,將流轉換為集合或其他形式。
// 轉換為List
List<String> list = names.stream().collect(Collectors.toList());// 轉換為Set
Set<String> set = names.stream().collect(Collectors.toSet());// 轉換為Map
Map<String, Integer> nameLengthMap = names.stream().collect(Collectors.toMap(name -> name, // 鍵String::length // 值));// 連接字符串
String joined = names.stream().collect(Collectors.joining(", "));// 分組
Map<Integer, List<String>> groupByLength = names.stream().collect(Collectors.groupingBy(String::length));
- distinct() - 去重
distinct() 去除流中的重復元素。
List<Integer> numbersWithDuplicates = Arrays.asList(1, 2, 2, 3, 4, 4, 5);// 基本去重
List<Integer> distinctNumbers = numbersWithDuplicates.stream().distinct().collect(Collectors.toList());// 對象去重(需要正確實現equals和hashCode)
List<Employee> distinctEmployees = employees.stream().distinct().collect(Collectors.toList());// 結合其他操作
List<String> distinctLongNames = names.stream().filter(name -> name.length() > 3).distinct().collect(Collectors.toList());
綜合使用示例
List<Transaction> transactions = getTransactions();
// 復雜流處理
Map<String, Double> result = transactions.stream().peek(t -> System.out.println("處理交易: " + t.getId())) // 調試.filter(t -> t.getAmount() > 1000) // 過濾小額交易.distinct() // 去重.skip(5) // 跳過前5條.limit(10) // 只取10條.collect(Collectors.groupingBy(Transaction::getCurrency, // 按貨幣分組Collectors.summingDouble(Transaction::getAmount) // 計算每種貨幣的總金額));