《Stream 流操作指南:让数据像奶茶配料一样丝滑流动》

154 阅读6分钟

Stream 流

Stream操作

Stream流就是流式处理数据,流的操作有很多种

  • 中间操作(真正处理数据的操作)
    • 中间操作就是执行完返回的是一个流,即可以**继续执行**流操作
    • 敲代码来说,就是使用中间操作的方法,写完继续再.调用其他方法
  • 终止操作(将操作完的结果返回)
    • 敲代码来说,调用终止方法,代码就结束;
操作函数说明
中间操作filter(Predicate)将结果为false的元素过滤掉
中间操作map(Function)转换元素的值,可以用方法引元或者lambda表达式
中间操作flatMap(Function)若元素是流,将流摊平为正常元素,再进行元素转换(合并两个流为一个流)
中间操作limit(long n)保留前n个元素
中间操作skip(long n)跳过前n个元素
中间操作concat(Stream s1, Stream s2)将两个流拼接起来
中间操作distinct()剔除重复元素
中间操作sorted()将Comparable元素的流排序
中间操作sorted(Comparator)将流元素按Comparator排序
中间操作peek(Consumer)流不变,但会把每个元素传入fun执行,可以用作调试
终结操作max(Comparator)取最大值
终结操作min(Comparator)取最小值
终结操作count()统计元素数量
终结操作findFirst()获得流的第一个元素
终结操作findAny()返回任意元素
终结操作anyMatch(Predicate)任意元素匹配时返回true
终结操作allMatch(Predicate)所有元素匹配时返回true
终结操作noneMatch(Predicate)没有元素匹配时返回true
终结操作reduce(Function)从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数
终结操作iterator()迭代器迭代元素
终结操作forEach(Consumer)lambda的方式迭代
终结操作forEachOrdered(Consumer)可以应用在并行流上以保持元素顺序

代码示例:

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamOperationExamples {
    public static void main(String[] args) {
        // 初始化一个包含 1 到 10 的整数列表
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 中间操作:filter(Predicate)
        // filter 方法用于过滤流中的元素,只保留满足 Predicate 条件的元素
        // 这里过滤出列表中所有的偶数
        List<Integer> filteredNumbers = numbers.stream()
               .filter(n -> n % 2 == 0)
               .collect(Collectors.toList());
        // 结果:[2, 4, 6, 8, 10]
        System.out.println("Filtered numbers: " + filteredNumbers);

        // 中间操作:map(Function)
        // map 方法用于对流中的每个元素应用一个函数,将元素转换为另一种形式
        // 这里将列表中的每个元素进行平方操作
        List<Integer> squaredNumbers = numbers.stream()
               .map(n -> n * n)
               .collect(Collectors.toList());
        // 结果:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
        System.out.println("Squared numbers: " + squaredNumbers);

        // 中间操作:flatMap(Function)
        // flatMap 方法用于将嵌套的流展开成一个单一流
        // 这里将一个包含多个子列表的列表展开成一个包含所有元素的列表
        List<List<Integer>> nestedList = Arrays.asList(
                Arrays.asList(1, 2),
                Arrays.asList(3, 4),
                Arrays.asList(5, 6)
        );
        List<Integer> flattenedList = nestedList.stream()
               .flatMap(List::stream)
               .collect(Collectors.toList());
        // 结果:[1, 2, 3, 4, 5, 6]
        System.out.println("Flattened list: " + flattenedList);

        // 中间操作:limit(long n)
        // limit 方法用于截取流中的前 n 个元素
        // 这里截取列表中的前 3 个元素
        List<Integer> limitedNumbers = numbers.stream()
               .limit(3)
               .collect(Collectors.toList());
        // 结果:[1, 2, 3]
        System.out.println("Limited numbers: " + limitedNumbers);

        // 中间操作:skip(long n)
        // skip 方法用于跳过流中的前 n 个元素
        // 这里跳过列表中的前 3 个元素
        List<Integer> skippedNumbers = numbers.stream()
               .skip(3)
               .collect(Collectors.toList());
        // 结果:[4, 5, 6, 7, 8, 9, 10]
        System.out.println("Skipped numbers: " + skippedNumbers);

        // 中间操作:concat(Stream s1, Stream s2)
        // concat 方法用于将两个流连接成一个流
        // 这里将两个包含整数的流连接成一个新的流
        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 5, 6);
        List<Integer> concatenatedStream = Stream.concat(stream1, stream2)
               .collect(Collectors.toList());
        // 结果:[1, 2, 3, 4, 5, 6]
        System.out.println("Concatenated stream: " + concatenatedStream);

        // 中间操作:distinct()
        // distinct 方法用于去除流中的重复元素
        // 这里去除列表中的重复元素
        List<Integer> numbersWithDuplicates = Arrays.asList(1, 2, 2, 3, 3, 3);
        List<Integer> distinctNumbers = numbersWithDuplicates.stream()
               .distinct()
               .collect(Collectors.toList());
        // 结果:[1, 2, 3]
        System.out.println("Distinct numbers: " + distinctNumbers);

        // 中间操作:sorted()
        // sorted 方法用于对流中的元素进行自然排序(元素需实现 Comparable 接口)
        // 这里对列表中的元素进行自然排序
        List<Integer> sortedNumbers = numbers.stream()
               .sorted()
               .collect(Collectors.toList());
        // 结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        System.out.println("Sorted numbers: " + sortedNumbers);

        // 中间操作:sorted(Comparator)
        // sorted 方法的重载形式,使用自定义的 Comparator 进行排序
        // 这里对列表中的元素进行逆序排序
        List<Integer> reverseSortedNumbers = numbers.stream()
               .sorted(Comparator.reverseOrder())
               .collect(Collectors.toList());
        // 结果:[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
        System.out.println("Reverse sorted numbers: " + reverseSortedNumbers);

        // 中间操作:peek(Consumer)
        // peek 方法用于在流的每个元素上执行一个操作,但不会改变流中的元素
        // 通常用于调试,这里打印出每个元素
        List<Integer> peekedNumbers = numbers.stream()
               .peek(n -> System.out.println("Peeked number: " + n))
               .collect(Collectors.toList());
        // 结果:打印出每个元素,最终集合为 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        System.out.println("Peeked numbers: " + peekedNumbers);

        // 终结操作:max(Comparator)
        // max 方法用于找出流中的最大值,需要传入一个 Comparator 来定义比较规则
        // 这里找出列表中的最大值
        Optional<Integer> maxNumber = numbers.stream()
               .max(Comparator.naturalOrder());
        // 结果:10
        System.out.println("Max number: " + maxNumber.orElse(null));

        // 终结操作:min(Comparator)
        // min 方法用于找出流中的最小值,需要传入一个 Comparator 来定义比较规则
        // 这里找出列表中的最小值
        Optional<Integer> minNumber = numbers.stream()
               .min(Comparator.naturalOrder());
        // 结果:1
        System.out.println("Min number: " + minNumber.orElse(null));

        // 终结操作:count()
        // count 方法用于统计流中元素的数量
        // 这里统计列表中元素的数量
        long count = numbers.stream().count();
        // 结果:10
        System.out.println("Count: " + count);

        // 终结操作:findFirst()
        // findFirst 方法用于获取流中的第一个元素
        // 这里获取列表中的第一个元素
        Optional<Integer> firstNumber = numbers.stream().findFirst();
        // 结果:1
        System.out.println("First number: " + firstNumber.orElse(null));

        // 终结操作:findAny()
        // findAny 方法用于获取流中的任意一个元素
        // 这里获取列表中的任意一个元素
        Optional<Integer> anyNumber = numbers.stream().findAny();
        // 结果:可能是 1 到 10 中的任意一个(这里一般是 1)
        System.out.println("Any number: " + anyNumber.orElse(null));

        // 终结操作:anyMatch(Predicate)
        // anyMatch 方法用于检查流中是否有任意一个元素满足 Predicate 条件
        // 这里检查列表中是否有大于 5 的元素
        boolean anyMatch = numbers.stream().anyMatch(n -> n > 5);
        // 结果:true
        System.out.println("Any number greater than 5: " + anyMatch);

        // 终结操作:allMatch(Predicate)
        // allMatch 方法用于检查流中的所有元素是否都满足 Predicate 条件
        // 这里检查列表中的所有元素是否都大于 0
        boolean allMatch = numbers.stream().allMatch(n -> n > 0);
        // 结果:true
        System.out.println("All numbers greater than 0: " + allMatch);

        // 终结操作:noneMatch(Predicate)
        // noneMatch 方法用于检查流中是否没有任何元素满足 Predicate 条件
        // 这里检查列表中是否没有小于 0 的元素
        boolean noneMatch = numbers.stream().noneMatch(n -> n < 0);
        // 结果:true
        System.out.println("No number less than 0: " + noneMatch);

        // 终结操作:reduce(Function)
        // reduce 方法用于将流中的元素进行累积操作
        // 这里使用 Integer 的 sum 方法将列表中的元素累加起来
        Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
        // 结果:55
        System.out.println("Sum of numbers: " + sum.orElse(null));

        // 终结操作:iterator()
        // iterator 方法用于获取流的迭代器,可用于手动遍历流中的元素
        // 这里使用迭代器遍历列表中的元素并打印
        java.util.Iterator<Integer> iterator = numbers.stream().iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        // 结果:打印出 1 2 3 4 5 6 7 8 9 10
        System.out.println();

        // 终结操作:forEach(Consumer)
        // forEach 方法用于对流中的每个元素执行一个操作
        // 这里使用 Lambda 表达式打印列表中的每个元素
        numbers.stream().forEach(n -> System.out.print(n + " "));
        // 结果:打印出 1 2 3 4 5 6 7 8 9 10
        System.out.println();

        // 终结操作:forEachOrdered(Consumer)
        // forEachOrdered 方法用于在并行流中按顺序对每个元素执行一个操作
        // 这里在并行流中按顺序打印列表中的每个元素
        numbers.parallelStream().forEachOrdered(n -> System.out.print(n + " "));
        // 结果:打印出 1 2 3 4 5 6 7 8 9 10
        System.out.println();
    }
}