java中stream流详细使用操作

一 stream的介绍

在Java中,Stream是一种用于对集合数据进行操作的API。它提供了一种函数式编程的方式来处理集合,使得代码更加简洁、优雅且易于并行化处理。Stream API允许你通过一系列的中间操作和终端操作来对集合数据进行处理。

二 基本使用

1.创建Stream: 可以通过Collection接口的stream()方法创建一个Stream,或者通过Stream类的静态方法of()generate()iterate()等创建Stream。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream1 = numbers.stream();

Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5);

Stream<Integer> stream3 = Stream.generate(() -> 1).limit(5);

Stream<Integer> stream4 = Stream.iterate(1, n -> n + 1).limit(5);

2.中间操作: 中间操作是指返回一个新Stream的操作,常用的中间操作包括filter()map()sorted()distinct()limit()等。

  • filter(Predicate<T> predicate): 过滤Stream中不符合条件的元素,并返回一个新的Stream。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    Stream<Integer> filteredStream = numbers.stream()
        .filter(n -> n % 2 == 0);
    
    // 使用forEach终端操作打印过滤后的结果
    filteredStream.forEach(System.out::println);
    // 输出结果:2 4
    
  • map(Function<T, R> mapper): 对Stream中的元素进行映射转换,并返回一个新的Stream。
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    
    Stream<String> mappedStream = names.stream()
        .map(name -> "Hello, " + name);
    
    // 使用forEach终端操作打印映射后的结果
    mappedStream.forEach(System.out::println);
    // 输出结果:Hello, Alice Hello, Bob Hello, Charlie
    
  • sorted(Comparator<T> comparator): 对Stream中的元素进行排序,并返回一个新的Stream。
    List<Integer> numbers = Arrays.asList(3, 1, 5, 2, 4);
    
    Stream<Integer> sortedStream = numbers.stream()
        .sorted();
    
    // 使用forEach终端操作打印排序后的结果
    sortedStream.forEach(System.out::println);
    // 输出结果:1 2 3 4 5
    
  • distinct(): 去除Stream中重复的元素,并返回一个新的Stream。
    List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
    
    Stream<Integer> distinctStream = numbers.stream()
        .distinct();
    
    // 使用forEach终端操作打印去重后的结果
    distinctStream.forEach(System.out::println);
    // 输出结果:1 2 3
    
  • limit(long maxSize): 截取Stream中的前n个元素,并返回一个新的Stream。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    Stream<Integer> limitedStream = numbers.stream()
        .limit(3);
    
    // 使用forEach终端操作打印截取后的结果
    limitedStream.forEach(System.out::println);
    // 输出结果:1 2 3
    

3.终端操作: 终端操作是指返回一个非Stream的结果的操作,用于触发Stream的计算。常用的终端操作包括forEach()collect()reduce()min()max()count()等。

  • forEach(Consumer<T> action): 对Stream中的每个元素执行指定操作,没有返回值。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    numbers.stream()
        .forEach(System.out::println);
    // 输出结果:1 2 3 4 5
    
  • collect(Collector<T, A, R> collector): 对Stream中的元素进行汇总操作,返回一个结果集合。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    List<Integer> collectedList = numbers.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());
    
    System.out.println(collectedList);
    // 输出结果:[2, 4]
    
  • reduce(BinaryOperator<T> accumulator): 对Stream中的元素进行聚合操作,返回一个Optional结果。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    Optional<Integer> sum = numbers.stream()
        .reduce(Integer::sum);
    
    System.out.println(sum);
    // 输出结果:Optional[15]
    
  • min(Comparator<T> comparator): 找到Stream中的最小元素,返回一个Optional结果。
    List<Integer> numbers = Arrays.asList(3, 1, 5, 2, 4);
    
    Optional<Integer> min = numbers.stream()
        .min(Integer::compare);
    
    System.out.println(min);
    // 输出结果:Optional[1]
    
  • max(Comparator<T> comparator): 找到Stream中的最大元素,返回一个Optional结果。
    List<Integer> numbers = Arrays.asList(3, 1, 5, 2, 4);
    
    Optional<Integer> max = numbers.stream()
        .max(Integer::compare);
    
    System.out.println(max);
    // 输出结果:Optional[5]
    

  • count(): 统计Stream中的元素数量,返回一个long类型的结果。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    long count = numbers.stream()
        .count();
    
    System.out.println(count);
    // 输出结果:5
    

4.并行处理: Stream API支持并行处理,可以通过parallel()方法将Stream转换为并行Stream,以提高处理速度。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> parallelStream = numbers.parallelStream();

parallelStream.forEach(System.out::println);

以上是Java中Stream的一些常用操作,通过使用Stream API,你可以更加方便地对集合数据进行处理,并且代码会更加简洁和易于理解。需要注意的是,Stream是一次性的,一旦触发终端操作,Stream将会被关闭,不能再次使用。

三 扩展与优化

  1. 使用Lambda表达式和方法引用: 在中间操作和终端操作中,使用Lambda表达式和方法引用可以使代码更加简洁和易于理解。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    // 使用Lambda表达式
    List<Integer> filteredList = numbers.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());
    
    // 使用方法引用
    List<String> mappedList = filteredList.stream()
        .map(n -> "Number: " + n)
        .collect(Collectors.toList());
    
  2. 使用orElseorElseGet 在使用Optional时,可以使用orElseorElseGet来提供默认值,避免返回null。
    Optional<Integer> optionalValue = numbers.stream()
        .filter(n -> n > 10)
        .findFirst();
    
    // 使用orElse
    Integer value = optionalValue.orElse(-1);
    
    // 使用orElseGet
    Integer value = optionalValue.orElseGet(() -> expensiveOperation());
    
  3. 使用findFirstfindAny 在找到第一个元素时,使用findFirst,如果仅需要一个元素而不关心具体是哪个元素,可以使用findAny。在并行处理时,findAny性能更好。
    Optional<Integer> firstValue = numbers.stream()
        .findFirst();
    
    Optional<Integer> anyValue = numbers.parallelStream()
        .findAny();
    
  4. 避免不必要的中间操作: Stream的中间操作是惰性求值的,只有在终端操作时才会触发计算。因此,应尽量避免不必要的中间操作,以提高性能。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    // 不必要的中间操作
    List<Integer> filteredList = numbers.stream()
        .filter(n -> n % 2 == 0)
        .map(n -> n * 2)
        .collect(Collectors.toList());
    
    // 优化后的操作
    List<Integer> optimizedList = numbers.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());
    
  5. 使用flatMap 当处理嵌套集合时,可以使用flatMap将嵌套集合展平成一个新的Stream。
    List<List<Integer>> nestedList = Arrays.asList(
        Arrays.asList(1, 2, 3),
        Arrays.asList(4, 5, 6),
        Arrays.asList(7, 8, 9)
    );
    
    List<Integer> flattenedList = nestedList.stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());
    
  6. 使用并行Stream: 在大规模数据处理时,可以使用并行Stream来提高处理速度。但是需要注意,不是所有的场景都适合使用并行Stream,因为并行处理可能引发线程安全问题。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
    // 串行处理
    numbers.stream()
        .forEach(System.out::println);
    
    // 并行处理
    numbers.parallelStream()
        .forEach(System.out::println);
    

总之,使用Stream API可以使代码更加简洁、易读和高效。在扩展和优化Stream操作时,需要根据具体场景合理选择不同的操作方法,以满足需求并提升性能。同时,遵循函数式编程的原则,避免副作用和共享状态,可以更好地利用Stream API的优势。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值