当前位置:首页 » 《休闲阅读》 » 正文

Java Stream流 这篇就够了 详细教程

14 人参与  2024年09月12日 18:41  分类 : 《休闲阅读》  评论

点击全文阅读


目录

1.概述

2.Steam操作 

中间操作(Intermediate operations)

(1)filter

 (2)map

 (3)flatMap

 (4)sorted

 (5)peek

(6) limit

(7) skip

 (8)distinct

终端操作(Terminal operations)

(1)forEach

(2) collect

(3) reduce

(4)toArray

(5)min

(6)max

(7)count

(8)anyMatch

(9)allMatch

(10)noneMatch

(11)findFirst

(12)findAny

3.创建 Stream

(1) stream

 (2) Arrays.stream

(3) Stream.of

 (4) Stream.iterate

4.并行 Streams

(1)parallelStream

 (2)parallel

5.Collectors

(1)toList

(2)toSet

(3)toMap

(4)joining

(5)counting

6.使用 Stream 的注意事项


1. 概述

        Java Stream API 是 Java 8 及以上版本中提供的一种新特性,它支持对集合(Collections)进行声明式的操作。Stream API 可以用于执行复杂的数据转换操作,并支持并行处理。

2. Steam操作 

中间操作(Intermediate operations)

中间操作返回的是一个新的 Stream,可以继续进行链式调用。以下是一些常见的中间操作:

(1)filter

filter(Predicate<? super T> predicate): 过滤元素。

示例: 过滤出列表中所有偶数。

        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]

 (2)map

map(Function<? super T, ? extends R> mapper): 转换每个元素到对应的结果。

示例: 将每个字符串转换为大写。

        List<String> words = Arrays.asList("hello", "world");        List<String> upperCaseWords = words.stream()                                           .map(String::toUpperCase)                                           .collect(Collectors.toList());        System.out.println(upperCaseWords); // 输出 [HELLO, WORLD]

 (3)flatMap

flatMap(Function<? super T, ? extends Stream<? extends R>> mapper): 将每个元素转换成另一个 Stream,然后将所有流连接成一个流。

示例:将包含单词列表的列表转换为单词流。

        List<List<String>> listOfLists = Arrays.asList(            Arrays.asList("hello", "world"),            Arrays.asList("goodbye", "world")        );        List<String> words = listOfLists.stream()                                         .flatMap(List::stream)                                         .collect(Collectors.toList());        System.out.println(words); // 输出 [hello, world, goodbye, world]

 (4)sorted

sorted(): 对元素进行自然排序。

示例:对整数列表进行自然排序。

        List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);        List<Integer> sortedNumbers = numbers.stream()                                             .sorted()                                             .collect(Collectors.toList());        System.out.println(sortedNumbers); // 输出 [1, 1, 3, 4, 5, 9]

 

sorted(Comparator<? super T> comparator): 使用提供的比较器对元素进行排序。

示例:使用自定义比较器对字符串列表进行排序。

 List<String> words = Arrays.asList("banana", "apple", "cherry");        List<String> sortedWords = words.stream()                                        .sorted(Comparator.reverseOrder())                                        .collect(Collectors.toList());        System.out.println(sortedWords); // 输出 [cherry, banana, apple]

 (5)peek

peek(Consumer<? super T> action): 用于调试,允许你无修改地查看流中的元素。

示例:打印每个元素,用于调试。 

        List<String> words = Arrays.asList("hello", "world");        List<String> upperCaseWords = words.stream()                                           .peek(System.out::println) // 打印每个元素                                           .map(String::toUpperCase)                                           .collect(Collectors.toList());

(6) limit

limit(long maxSize): 限制流的大小。

示例:限制流的大小。

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);        List<Integer> limitedNumbers = numbers.stream()                                              .limit(3)                                              .collect(Collectors.toList());        System.out.println(limitedNumbers); // 输出 [1, 2, 3]

(7) skip

skip(long n): 跳过流中的前 n 个元素。

示例:跳过列表中的前 n 个元素。

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);        List<Integer> skippedNumbers = numbers.stream()                                              .skip(3)                                              .collect(Collectors.toList());        System.out.println(skippedNumbers); // 输出 [4, 5, 6, 7, 8, 9]

 (8)distinct

distinct(): 去除重复元素。

示例:

        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5, 5, 5, 6);        List<Integer> distinctNumbers = numbers.stream()                                               .distinct()                                               .collect(Collectors.toList());        System.out.println(distinctNumbers); // 输出 [1, 2, 3, 4, 5, 6]

终端操作(Terminal operations)

终端操作返回的是一个结果或一个副作用(例如打印结果),之后不能再对 Stream 进行操作。以下是一些常见的终端操作:

(1)forEach

forEach(Consumer<? super T> action): 对每个元素执行一个操作。

示例:对每个元素执行打印操作。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:打印每个元素        words.stream().forEach(System.out::println);         // apple        // banana        // cherry

(2) collect

collect(Collector<? super T, A, R> collector): 将流转换为其他形式,如列表、集合或 Map。

示例:将流转换为列表。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:将流转换为列表 [APPLE, BANANA, CHERRY]        List<String> upperCaseWords = words.stream()                                           .map(String::toUpperCase)                                           .collect(Collectors.toList());        System.out.println(upperCaseWords);

(3) reduce

reduce(T identity, BinaryOperator<T> accumulator): 通过一个起始值,反复利用 BinaryOperator 来处理和累积元素,返回一个值。

示例:使用 Integer::sum 作为累加器,将流中的整数相加。

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);        // 预期结果:计算总和 15        int sum = numbers.stream().reduce(0, Integer::sum);        System.out.println(sum); // 15
reduce(BinaryOperator<T> accumulator): 使用一个 BinaryOperator 来累积元素,返回一个 Optional。

示例: 使用 Integer::max 作为累加器,找到流中的最大值。

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);        // 预期结果:找到最大值 5        Optional<Integer> max = numbers.stream().reduce(Integer::max);        max.ifPresent(System.out::println); // 5

(4)toArray

toArray(): 将流转换为对象数组。

示例:使用 toArray 方法将流转换为对象数组。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:将流转换为对象数组 [apple, banana, cherry]        Object[] wordArray = words.stream().toArray();        System.out.println(Arrays.toString(wordArray));
toArray(IntFunction<A[]> generator): 将流转换为特定类型的数组。

示例:使用 toArray 方法将流转换为特定类型的数组。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:将流转换为字符串数组 [apple, banana, cherry]        String[] wordArray = words.stream().toArray(String[]::new);        System.out.println(Arrays.toString(wordArray));

(5)min

min(Comparator<? super T> comparator): 找到最小元素。

示例:使用 min 方法找到流中的最小元素。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:找到最小元素 apple        Optional<String> min = words.stream().min(String::compareTo);        min.ifPresent(System.out::println); // apple

(6)max

max(Comparator<? super T> comparator): 找到最大元素。

示例:使用 max 方法找到流中的最大元素。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:找到最大元素 cherry        Optional<String> max = words.stream().max(String::compareTo);        max.ifPresent(System.out::println); // cherry

(7)count

count(): 返回流中元素的数量。

示例:使用 count 方法返回流中元素的数量。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:流中元素的数量 3        long count = words.stream().count();        System.out.println(count); // 3

(8)anyMatch

anyMatch(Predicate<? super T> predicate): 检查是否至少有一个元素匹配给定的谓词。

示例: 这个方法用于检查流中是否至少有一个元素匹配给定的谓词。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:至少有一个元素以 "a" 开头        boolean anyMatch = words.stream().anyMatch(s -> s.startsWith("a"));        System.out.println(anyMatch); // 输出 true

(9)allMatch

allMatch(Predicate<? super T> predicate): 检查是否所有元素都匹配给定的谓词。

示例:这个方法用于检查流中是否所有元素都匹配给定的谓词。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:所有元素都以 "c" 开头        boolean allMatch = words.stream().allMatch(s -> s.startsWith("c"));        System.out.println(allMatch); // 输出 false

 

(10)noneMatch

noneMatch(Predicate<? super T> predicate): 检查是否没有元素匹配给定的谓词。

示例: 这个方法用于检查流中是否没有元素匹配给定的谓词。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:没有元素以 "z" 开头        boolean noneMatch = words.stream().noneMatch(s -> s.startsWith("z"));        System.out.println(noneMatch); // 输出 true

 

(11)findFirst

findFirst(): 返回第一个元素。

示例:这个方法用于返回流中的第一个元素。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:返回第一个元素 "apple"        Optional<String> first = words.stream().findFirst();        first.ifPresent(System.out::println); // apple

 

(12)findAny

findAny(): 返回任意一个元素(在并行流中特别有用)。

示例:这个方法用于返回流中的任意一个元素。

        List<String> words = Arrays.asList("apple", "banana", "cherry");        // 预期结果:返回任意一个元素,可能是 "apple", "banana" 或 "cherry"        Optional<String> any = words.stream().findAny();        any.ifPresent(System.out::println); // 输出一个随机的字符串元素

3. 创建 Stream

创建 Stream 的方式有很多:

(1) stream

通过集合的 stream() 方法。

示例:

        List<String> list = Arrays.asList("apple", "banana", "cherry");        Stream<String> stream = list.stream();

 (2) Arrays.stream

通过数组的 Arrays.stream(Object[]) 方法。

示例:

        String[] array = {"apple", "banana", "cherry"};        Stream<String> stream = Arrays.stream(array);

(3) Stream.of

使用 Stream.of(T... values) 静态方法。

示例:

        Stream<String> stream = Stream.of("apple", "banana", "cherry");

 (4) Stream.iterate

使用 Stream.iterate(T seed, UnaryOperator<T> f)或 Stream.generate(Supplier<T> s) 创建无限流。
        // 使用 Stream.iterate 创建无限流        Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);        // 使用 Stream.generate 创建无限流        Stream<String> generateStream = Stream.generate(() -> "hello");

4. 并行 Streams

  Stream 接口还有一个子接口 BaseStream 和一个并行流接口 ParallelStream,用于并行处理数据。

        并行流可以提高处理大量数据时的性能,因为它可以利用多核处理器的能力来并行地执行操作。但是,并不是所有的流操作都适合并行处理,你需要根据具体的情况来决定是否使用并行流

(1)parallelStream

 parallelStream() 方法,该方法是 Stream 接口的一个扩展方法。

示例:

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);        // 创建并行流        List<Integer> evenNumbers = numbers.parallelStream()                                           .filter(n -> n % 2 == 0)                                           .collect(Collectors.toList());        System.out.println(evenNumbers); // 输出 [2, 4, 6, 8]

 (2)parallel

parallel() 方法,该方法是 BaseStream 接口的一个扩展方法。
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);        // 使用 parallel() 方法创建并行流        List<Integer> evenNumbers = numbers.stream()                                             .parallel() // 创建并行流                                             .filter(n -> n % 2 == 0) // 过滤偶数                                             .collect(Collectors.toList()); // 收集结果        System.out.println(evenNumbers); // 输出 [2, 4, 6, 8]

 

5. Collectors

Collectors 类提供了很多静态方法,用于实现常见的归约操作,如将元素累积到集合、字符串、Map 等。

(1)toList

toList(): 将流中的元素收集到列表中。

示例:

        List<String> words = Arrays.asList("apple", "banana", "cherry");        List<String> collectedWords = words.stream().collect(Collectors.toList());        System.out.println(collectedWords); // 输出 [apple, banana, cherry]

(2)toSet

toSet(): 将流中的元素收集到集合中,自动去除重复项。

示例:

        List<String> words = Arrays.asList("apple", "banana", "cherry", "apple", "banana");        Set<String> collectedWords = words.stream().collect(Collectors.toSet());        System.out.println(collectedWords); // 输出 [apple, banana, cherry]

(3)toMap

toMap(): 将流中的元素收集到 Map 中,其中流中的元素作为键或值。

示例:

        List<String> words = Arrays.asList("apple", "banana", "cherry");        Map<String, Integer> wordCount = words.stream().collect(Collectors.toMap(            word -> word,            word -> word.length()        ));        System.out.println(wordCount); // 输出 {apple=5, banana=6, cherry=6}

(4)joining

joining(): 将流中的元素连接成一个字符串。

示例:

        List<String> words = Arrays.asList("apple", "banana", "cherry");        String joinedString = words.stream().collect(Collectors.joining("-"));        System.out.println(joinedString); // 输出 apple-banana-cherry

(5)counting

counting(): 计算流中元素的数量。

示例:

        List<String> words = Arrays.asList("apple", "banana", "cherry");        long wordCount = words.stream().collect(Collectors.counting());        System.out.println(wordCount); // 输出 3

6. 使用 Stream 的注意事项

流一旦执行终端操作,就会被消耗掉,不可以再使用该流执行其他操作。流操作不会改变原始数据源,所有的操作都会返回一个新的 Stream 对象。流操作可以并行化,但需要注意线程安全和数据竞争问题。

点击全文阅读


本文链接:http://zhangshiyu.com/post/158977.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1