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

目录

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 对象。
  • 流操作可以并行化,但需要注意线程安全和数据竞争问题。
  • 9
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java StreamJava 8中引入的新特性,它提供了一种简洁、高效的处理集合(List、Set、Map等)和数组的方式。它可以让我们在不改变原有数据结构的基础上,以一种函数式编程的方式操作数据,使代码更加简洁易懂。 下面是Java Stream的一些常用方法及其使用方式: 1. filter:过滤 filter方法可以过滤掉不符合条件的元素,只留下符合条件的元素。 例如: ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNums = nums.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()); ``` 这段代码将nums集合中的偶数过滤出来,得到一个新的集合evenNums。 2. map:映射 map方法可以将集合中的每个元素映射成另一个元素。 例如: ```java List<String> words = Arrays.asList("hello", "world"); List<Integer> wordLengths = words.stream().map(String::length).collect(Collectors.toList()); ``` 这段代码将words集合中的每个元素(字符串)的长度映射成一个新的集合wordLengths。 3. flatMap:扁平化 flatMap方法可以将多个集合合并成一个集合。 例如: ```java List<List<Integer>> numsList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6)); List<Integer> nums = numsList.stream().flatMap(Collection::stream).collect(Collectors.toList()); ``` 这段代码将numsList中的所有元素合并成一个新的集合nums。 4. forEach:遍历 forEach方法可以遍历集合中的每个元素。 例如: ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); nums.stream().forEach(System.out::println); ``` 这段代码将nums集合中的每个元素打印出来。 5. reduce:归约 reduce方法可以将集合中的多个元素归约成一个元素。 例如: ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); int sum = nums.stream().reduce(0, Integer::sum); ``` 这段代码将nums集合中的所有元素相加得到一个sum值。 以上是Java Stream的一些常用方法及其使用方式,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

探索星辰大海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值