在Java 8中芒粹,引入了一種新的處理集合數(shù)據(jù)的方式——Stream呛踊。Stream可以讓我們更方便地對集合數(shù)據(jù)進(jìn)行處理,同時也提供了更好的性能和并行處理能力。在工作中卓囚,對集合的處理尤為常見,所以今天來聊一聊Stream
什么是Stream谤专?
Stream是Java 8中引入的一個新的API牺丙,它允許我們以聲明性的方式對集合數(shù)據(jù)進(jìn)行操作。Stream可以處理任何類型的數(shù)據(jù)抒抬,包括基本數(shù)據(jù)類型杨刨、對象和數(shù)組等。它提供了一種簡單而強(qiáng)大的方式來對數(shù)據(jù)進(jìn)行過濾擦剑、轉(zhuǎn)換妖胀、排序和聚合等操作。
如何創(chuàng)建Stream惠勒?
Stream可以從多種數(shù)據(jù)源創(chuàng)建赚抡,包括集合、數(shù)組纠屋、文件涂臣、網(wǎng)絡(luò)等。以下是一些創(chuàng)建Stream的示例:
// 從集合中創(chuàng)建Stream
List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = list.stream();
// 從數(shù)組中創(chuàng)建Stream
int[] array = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(array);
// 從文件中創(chuàng)建Stream
Stream<String> lines = Files.lines(Paths.get("filename.txt"));
// 創(chuàng)建無限Stream
Stream<Integer> stream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6, ...
如何操作Stream售担?
Stream提供了許多操作赁遗,可以分為中間操作和終端操作兩類。中間操作返回的是一個新的Stream對象族铆,可以進(jìn)行連續(xù)的操作吼和;終端操作會產(chǎn)生一個最終的結(jié)果,結(jié)束整個操作流程骑素。
以下是一些常用的Stream操作:
中間操作
- filter(Predicate<T> predicate):根據(jù)指定的條件過濾Stream中的元素炫乓;
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = names.stream()
.filter(name -> name.length() > 4)
.collect(Collectors.toList());
System.out.println(filteredNames); // Output: [Charlie, David]
- map(Function<T, R> mapper):將Stream中的元素映射為另一種類型;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println(squaredNumbers); // Output: [1, 4, 9, 16, 25]
- sorted(Comparator<T> comparator):根據(jù)指定的比較器對Stream中的元素進(jìn)行排序献丑;
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> sortedNames = names.stream()
.sorted((name1, name2) -> name1.compareTo(name2))
.collect(Collectors.toList());
System.out.println(sortedNames); // Output: [Alice, Bob, Charlie, David]
- distinct():去除Stream中重復(fù)的元素末捣;
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 4, 5, 4, 3);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers); // Output: [1, 2, 3, 4, 5]
- limit(long maxSize):返回一個不超過指定大小的Stream;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
System.out.println(limitedNumbers); // Output: [1, 2, 3]
- skip(long n):跳過前n個元素创橄,返回剩余的Stream箩做。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
System.out.println(skippedNumbers); // Output: [3, 4, 5]
終端操作
- forEach(Consumer<T> action):對Stream中的每個元素執(zhí)行指定的操作;
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.forEach(name -> System.out.println("Hello, " + name + "!"));
// Output: Hello, Alice!
// Hello, Bob!
// Hello, Charlie!
// Hello, David!
- toArray():將Stream中的元素轉(zhuǎn)換為數(shù)組妥畏;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer[] numberArray = numbers.stream()
.toArray(Integer[]::new);
System.out.println(Arrays.toString(numberArray)); // Output: [1, 2, 3, 4, 5]
- reduce(T identity, BinaryOperator<T> accumulator):將Stream中的元素依次歸約為一個值邦邦;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println(sum); // Output: 15
- collect(Collector<T, A, R> collector):將Stream中的元素轉(zhuǎn)換為另一種形式安吁,例如List、Map等燃辖;
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Map<String, Integer> nameLengths = names.stream()
.collect(Collectors.toMap(
name -> name,
name -> name.length()));
System.out.println(nameLengths); // Output: {Alice=5, Bob=3, Charlie=7, David=5}
- count():返回Stream中的元素個數(shù)鬼店;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
.count();
System.out.println(count); // Output: 5
- anyMatch(Predicate<T> predicate):判斷Stream中是否存在滿足指定條件的元素;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEvenNumber = numbers.stream()
.anyMatch(n -> n % 2 == 0);
System.out.println(hasEvenNumber); // Output: true
- allMatch(Predicate<T> predicate):判斷Stream中是否所有元素都滿足指定條件黔龟;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allNumbersArePositive = numbers.stream()
.allMatch(n -> n > 0);
System.out.println(allNumbersArePositive); // Output: true
- noneMatch(Predicate<T> predicate):判斷Stream中是否不存在滿足指定條件的元素妇智;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noNegativeNumbers = numbers.stream()
.noneMatch(n -> n < 0);
System.out.println(noNegativeNumbers); // Output: true
- findFirst():返回Stream中的第一個元素;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstNumber = numbers.stream()
.findFirst();
System.out.println(firstNumber); // Output: Optional[1]
- findAny():返回Stream中的任意一個元素氏身;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> anyNumber = numbers.stream()
.filter(n -> n % 2 == 0)
.findAny();
System.out.println(anyNumber); // Output: Optional[2] (or Optional[4], depending on the stream implementation)
- max(Comparator<T> comparator):返回Stream中的最大元素巍棱;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> maxNumber = numbers.stream()
.max((n1, n2) -> n1.compareTo(n2));
System.out.println(maxNumber); // Output: Optional[5]
- min(Comparator<T> comparator):返回Stream中的最小元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> minNumber = numbers.stream()
.min((n1, n2) -> n1.compareTo(n2));
System.out.println(minNumber); // Output: Optional[1]
Stream的并行處理能力
Stream還提供了并行處理能力蛋欣,可以在多個線程上同時處理數(shù)據(jù)航徙,提高處理速度。只需要在創(chuàng)建Stream對象時陷虎,調(diào)用parallel()方法即可啟用并行處理到踏。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.parallelStream().mapToInt(Integer::intValue).sum();
需要注意的是,并不是所有的操作都適合并行處理泻红,例如排序和去重等操作會影響并行處理的效率夭禽。
Stream的優(yōu)點
使用Stream處理數(shù)據(jù)有以下幾個優(yōu)點:
- 聲明性的代碼:可以更清晰地表達(dá)數(shù)據(jù)的處理流程霞掺,減少冗余代碼谊路;
- 更好的性能:Stream可以充分利用多核處理器的性能,提高數(shù)據(jù)處理效率菩彬;
- 與Lambda表達(dá)式結(jié)合使用:可以更方便地處理數(shù)據(jù)缠劝,減少代碼的復(fù)雜度和冗余度。
結(jié)論
Stream是Java 8中一個強(qiáng)大的API骗灶,可以幫助我們更方便地處理集合數(shù)據(jù)惨恭,同時提供了更好的性能和并行處理能力。掌握Stream的相關(guān)技術(shù)耙旦,可以讓我們的代碼更加簡潔脱羡、高效、易于維護(hù)免都。