Java 開發(fā)者必備:Stream API 的核心用法與實(shí)戰(zhàn)技巧
Java 8 引入了 Stream API,使得我們可以更加簡(jiǎn)潔、高效地處理集合。Stream API 提供了一種函數(shù)式編程風(fēng)格的操作集合的方法,使代碼更簡(jiǎn)潔、可讀性更高。本文將詳細(xì)介紹 Java Stream API 的基本用法和一些實(shí)踐技巧。
什么是 Stream API
Stream 是 Java 8 引入的一個(gè)新的抽象,它代表一個(gè)支持?jǐn)?shù)據(jù)處理操作的序列。Stream 以函數(shù)式編程的方式處理數(shù)據(jù),可以執(zhí)行過濾、映射、規(guī)約等操作。與傳統(tǒng)的集合不同,Stream 不存儲(chǔ)數(shù)據(jù),而是按需計(jì)算。
Stream 的創(chuàng)建方式
可以通過多種方式創(chuàng)建 Stream,常見的方法如下:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamCreation {
public static void main(String[] args) {
// 從集合創(chuàng)建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> streamFromList = list.stream();
// 從數(shù)組創(chuàng)建
String[] array = {"x", "y", "z"};
Stream<String> streamFromArray = Arrays.stream(array);
// 使用 Stream.of 創(chuàng)建
Stream<String> streamOf = Stream.of("1", "2", "3");
// 創(chuàng)建無限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
// 打印流中的元素
streamFromList.forEach(System.out::println);
streamFromArray.forEach(System.out::println);
streamOf.forEach(System.out::println);
infiniteStream.limit(5).forEach(System.out::println);
}
}
常見的中間操作
中間操作返回一個(gè)新的 Stream,對(duì)原有 Stream 進(jìn)行處理。常見的中間操作有 filter、map、sorted 和 distinct 等。
filter - 過濾元素
filter 方法用于過濾元素:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamFilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // 輸出: [2, 4, 6]
}
}
map - 映射元素
map 方法用于將元素映射為新的元素:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamMapExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(wordLengths); // 輸出: [5, 5]
}
}
sorted - 排序元素
sorted 方法用于對(duì)元素進(jìn)行排序:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortedExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers); // 輸出: [1, 2, 3, 4, 5]
}
}
distinct - 去重元素
distinct 方法用于去除重復(fù)元素:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamDistinctExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers); // 輸出: [1, 2, 3, 4, 5]
}
}
常見的終端操作
終端操作會(huì)觸發(fā) Stream 的執(zhí)行,并返回一個(gè)結(jié)果。常見的終端操作有 forEach、collect、reduce 和 count 等。
forEach - 遍歷元素
forEach 方法用于遍歷每一個(gè)元素:
import java.util.Arrays;
import java.util.List;
public class StreamForEachExample {
public static void main(String[] args) {
List<String> items = Arrays.asList("a", "b", "c");
items.stream().forEach(System.out::println);
}
}
collect - 收集元素
collect 方法用于將 Stream 的元素收集到一個(gè)集合中:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamCollectExample {
public static void main(String[] args) {
List<String> items = Arrays.asList("a", "b", "c");
List<String> collectedItems = items.stream()
.collect(Collectors.toList());
System.out.println(collectedItems); // 輸出: [a, b, c]
}
}
reduce - 規(guī)約元素
reduce 方法用于將元素組合起來:
import java.util.Arrays;
import java.util.List;
public class StreamReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum); // 輸出: 15
}
count - 統(tǒng)計(jì)元素個(gè)數(shù)
count 方法用于計(jì)算元素的個(gè)數(shù):
import java.util.Arrays;
import java.util.List;
public class StreamCountExample {
public static void main(String[] args) {
List<String> items = Arrays.asList("a", "b", "c");
long count = items.stream().count();
System.out.println(count); // 輸出: 3
}
}
實(shí)戰(zhàn)技巧
并行流 - 提高性能
并行流可以利用多核處理器的優(yōu)勢(shì),加快流操作的執(zhí)行速度??梢酝ㄟ^ parallelStream 方法創(chuàng)建并行流:
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
.reduce(0, Integer::sum);
System.out.println(sum); // 輸出: 15
}
}
組合多個(gè) Stream
可以使用 flatMap 方法將多個(gè) Stream 組合為一個(gè):
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamFlatMapExample {
public static void main(String[] args) {
List<List<Integer>> listOfLists = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9)
);
List<Integer> combinedList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(combinedList); // 輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
錯(cuò)誤處理
在流操作中,可能會(huì)出現(xiàn)異常,可以使用 peek 方法進(jìn)行調(diào)試:
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class StreamErrorHandlingExample {
public static void main(String[] args) {
List<String> items = Arrays.asList("1", "2", "a", "4");
List<Integer> numbers = items.stream()
.map(item -> {
try {
return Integer.parseInt(item);
} catch (NumberFormatException e) {
System.err.println("Error parsing: " + item);
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
System.out.println(numbers); // 輸出: [1, 2, 4]
}
}
注意事項(xiàng)
- 流的惰性求值:中間操作是惰性求值的,只有終端操作執(zhí)行時(shí)才會(huì)觸發(fā)實(shí)際的計(jì)算。
- 不可重用:Stream 一旦使用完畢,不能再次使用。如果需要再次使用,需要重新生成 Stream。
- 并行流的使用:并行流在某些情況下可以顯著提高性能,但并非所有場(chǎng)景都適用,應(yīng)根據(jù)實(shí)際情況進(jìn)行選擇。
結(jié)語(yǔ)
本文詳細(xì)介紹了 Java Stream API 的基本用法和一些實(shí)踐技巧。通過合理使用 Stream API,可以使代碼更加簡(jiǎn)潔、高效。希望讀者能夠通過本文的介紹,更好地掌握和應(yīng)用 Stream API。