JDK1.8 详解java.util.stream.Stream:Stream

1 篇文章 0 订阅
1 篇文章 0 订阅

介绍:

java.util.stream.Stream是Java 8引入的用于处理集合数据的API。它提供了一种函数式编程风格的操作方式,如过滤、映射、排序和归约等

详细解释和说明:

流(Stream)的概念:流是一系列元素的集合,它可以来自于数组、集合或其他数据源。流提供了一种高级抽象,允许以声明性的方式操作数据,而无需关心底层的实现细节。

流的特点:流具有以下几个特点:

流不存储数据,它只是对数据进行操作和处理。
流的操作可以是顺序的或并行的,使得可以更好地利用多核处理器的优势。
创建流:可以通过各种方式来创建流,包括从集合、数组、I/O通道等。

流的操作:流提供了一系列的中间操作和终端操作来对数据进行处理和操作。常见的操作包括过滤、映射、排序、去重、截取、归约等。

中间操作和终端操作:流的操作可以分为中间操作和终端操作两种类型。中间操作返回一个新的流,可以进行链式调用,而终端操作返回一个结果或副作用,终止了流的操作。

常用的Stream方法:Stream提供了许多常用的方法,如filter()、map()、sorted()、distinct()、limit()、forEach()、reduce()、collect()等,这些方法可以组合使用,以实现复杂的数据处理逻辑。

并行流:通过并行流,可以将数据的处理操作并行化,利用多核处理器的优势来提高性能。使用并行流时需要注意线程安全性和性能问题(并行流顺序流介绍)。

Stream与集合的区别:Stream与传统的集合操作相比,具有更高的抽象级别和表达能力。它可以提供更简洁、灵活、可读性强的代码,同时还可以更好地支持并行处理和延迟求值等特性。

Stream接口的定义:


```java
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    // ...
}

Stream接口继承自BaseStream接口,BaseStream接口定义了一些基本的流操作方法。

在Stream接口中,有许多用于操作流的方法,包括过滤、映射、排序、归约等。下面是一些常用的方法示例:

filter(Predicate<? super T> predicate):过滤流中的元素,只保留满足给定谓词条件的元素。

map(Function<? super T, ? extends R> mapper):对流中的每个元素应用一个函数,并将结果存储在新的流中。

sorted():对流中的元素进行排序,默认使用自然排序。

distinct():去除流中的重复元素。

limit(long maxSize):截取流中的前N个元素。

forEach(Consumer<? super T> action):对流中的每个元素执行给定的操作。

reduce(BinaryOperator<T> accumulator):使用给定的二进制操作符对流中的元素进行归约操作。

collect(Collector<? super T, A, R> collector):将流中的元素收集到一个结果容器中。

这些方法使得我们可以通过链式调用来对流进行一系列操作,从而实现复杂的数据处理逻辑。

Stream还提供了一些终端操作方法,用于触发流的计算和获取最终的结果,如forEach、reduce、collect等。

Stream的实现类包括ReferencePipeline、IntPipeline、LongPipeline和DoublePipeline等。这些实现类负责具体的流操作和流数据的处理。

注意:

惰性求值:Stream的操作是惰性求值的,只有在终端操作被调用时才会执行。因此,在编写代码时要注意确保至少有一个终端操作,否则中间操作不会执行。

线程安全性:并行流操作涉及多线程处理数据,因此要注意确保操作中的代码是线程安全的。避免在操作过程中修改共享的可变状态。

性能考虑:并行流可以利用多核处理器的优势,但并不意味着在所有情况下都比顺序流更快。在使用并行流时,要根据具体情况进行性能测试和评估,确保它能够带来性能上的提升。

流的重用:流一般是单次使用的。如果需要对同一组数据执行多个操作,应该创建多个流,而不是尝试在同一个流上多次调用终端操作。

以下是一些简单的代码示例:

   public static void main(String[] args) {
    //filter(Predicate<? super T> predicate):过滤流中的元素,只保留满足给定谓词条件的元素。
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
     List<Integer> filteredNumbers = numbers.stream()
      .filter(n -> n % 2 == 0)
            .collect(Collectors.toList());

    System.out.println(filteredNumbers);
    // 输出: [2, 4]
    //map(Function<? super T, ? extends R> mapper):对流中的每个元素应用一个函数,并将结果存储在新的流中。
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

    List<Integer> nameLengths = names.stream()
            .map(String::length)
            .collect(Collectors.toList());

    System.out.println(nameLengths);
    // 输出: [5, 3, 7]
    //sorted():对流中的元素进行排序,默认使用自然排序
    List<Integer> numbers1 = Arrays.asList(5, 2, 1, 4, 3);

    List<Integer> sortedNumbers = numbers1.stream()
            .sorted()
            .collect(Collectors.toList());

    System.out.println(sortedNumbers);
    // 输出: [1, 2, 3, 4, 5]
    //distinct():去除流中的重复元素。
    List<Integer> numbers2 = Arrays.asList(1, 2, 2, 3, 3, 4, 5, 5);

    List<Integer> distinctNumbers = numbers2.stream()
            .distinct()
            .collect(Collectors.toList());

    System.out.println(distinctNumbers);
    // 输出: [1, 2, 3, 4, 5]
    //limit(long maxSize):截取流中的前N个元素。
    List<Integer> numbers3 = Arrays.asList(1, 2, 3, 4, 5);

    List<Integer> limitedNumbers = numbers3.stream()
            .limit(3)
            .collect(Collectors.toList());

    System.out.println(limitedNumbers);
    // 输出: [1, 2, 3]
    //forEach(Consumer<? super T> action):对流中的每个元素执行给定的操作
    List<String> names4 = Arrays.asList("Alice", "Bob", "Charlie");

    names4.stream()
            .forEach(System.out::println);
    // 输出:
    // Alice
    // Bob
    // Charlie
    //reduce(BinaryOperator<T> accumulator):使用给定的二进制操作符对流中的元素进行归约操作。
    List<Integer> numbers5 = Arrays.asList(1, 2, 3, 4, 5);

    int sum = numbers5.stream()
            .reduce(0, (a, b) -> a + b);

    System.out.println(sum);
    // 输出: 15
    //collect(Collector<? super T, A, R> collector):将流中的元素收集到一个结果容器中
    List<String> names5 = Arrays.asList("Alice", "Bob", "Charlie");

    String concatenatedNames = names5.stream()
            .collect(Collectors.joining(", "));

    System.out.println(concatenatedNames);
    // 输出: Alice, Bob, Charlie
}

总结

  • Stream提供了一种声明性的方式来操作和处理集合数据,可以使代码更简洁、高效和可读性强。
  • 使用中间操作和终端操作的组合,可以构建复杂的数据处理逻辑。
  • 并行流可以提高处理大量数据的性能,但要注意线程安全性和性能问题。
  • 注意流的惰性求值特性,确保至少有一个终端操作来触发执行。
  • 避免在操作过程中修改共享的可变状态,保证线程安全性。
  • 流一般是单次使用的,如果需要多次操作同一组数据,应该创建多个流。
  • 了解并熟练使用Stream提供的常用方法,如过滤、映射、排序、归约等。
  • 结合函数式接口和Lambda表达式,可以更方便地对流进行操作。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值