Stream流式计算

1. 概述

Stream API ( java.util.stream ) 把真正的函数式编程风格引入到Java中。Stream 是 Java8 中处理集合的接口,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用 Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

实际开发中,项目中多数数据源都来自于 MySQL,Oracle 等。但现在数据源可以更多了,有 MongDB,Radis 等,而这些 NoSQL 的数据就需要 Java 层面去处理。

  • Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。
  • Stream 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合讲的是数据,Stream 讲的是计算!
  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新 Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream 的操作步骤:

  • 创建 Stream:一个数据源(如:集合、数组),获取一个流。
  • 中间操作:一个中间操作链,对数据源的数据进行处理。多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。
  • 终止操作:一旦执行终止操作,就执行中间操作链,并产生结果,其结果可以是任何不是流的值,例如:List、Integer、void。流进行了终止操作后,不能再次使用。

Stream 单线程串行计算:

  • Stream 接口默认是使用串行的方式,即在一个线程里执行。
  • Stream<User> stream = list.stream(); //返回一个顺序流

Stream 多线程并行计算:

  • Stream 并行计算的底层原理是使用了 Fork/Join 框架,更确切的说是使用 ForkJoinPool 里面的 commonPool 里面的 worker 线程完成并行计算,使得我们只需要写很少很简单的代码就可以利用计算机底层的多核资源。
  • Stream<User> parallelStream = list.parallelStream(); //返回一个并行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel()sequential() 在并行流与顺序流之间进行切换。

在多核的情况下,使用 Stream 的并行计算比串行计算能带来很大效率上的提升,并且也能保证结果计算完全准确。但并行计算耗时并不是单线程计算耗时除以处理器核数,因为线程的创建、销毁以及维护线程上下文的切换等等都有一定的开销。所以如果你的服务器并不是多核服务器,那也没必要用 Stream 的并行计算。因为在单核的情况下,往往 Stream 的串行计算比并行计算更快,因为它不需要线程切换的开销。

2. Stream的创建

package com.java.stream;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author rrqstart
 * @Description 创建Stream
 */
public class StreamTest1 {
   
    //创建Stream的方式1:通过集合Collection接口中提供的2个默认方法
    @Test
    public void test1() {
   
        User user1 = new User(1, "a", 21);
        User user2 = new User(2, "b", 22);
        User user3 = new User(3, "c", 23);
        User user4 = new User(4, "d", 24);
        User user5 = new User(6, "e", 25);

        List<User> list = Arrays.asList(user1, user2, user3, user4, user5);

        //default Stream<E> stream():返回一个顺序流
        Stream<User> stream = list.stream();

        //default Stream<E> parallelStream():返回一个并行流
        Stream<User> parallelStream = list.parallelStream();
    }

    //创建Stream的方式2:通过数组Arrays类中的静态方法stream()
    @Test
    public void test2() {
   
        User[] users = new User[5];

        //public static <T> Stream<T> stream(T[] array)
        Stream<User> stream = Arrays.stream(users);
    }

    //创建Stream的方式3:通过Stream类的静态方法of(),通过显示值创建一个流,它可以接收任意数量的参数。
    @Test
    public void test3() {
   
        //public static<T> Stream<T> of(T... values)
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
    }

    //创建Stream的方式4:通过Stream类的静态方法iterate()和generate()创建无限流
    @Test
    public void test4() {
   
        //迭代:public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        Stream<Integer> stream1 = Stream.iterate(0, t -> t + 2);
        stream1.limit(5).forEach(System.out::println); //遍历前5个偶数

        //生成:public static<T> Stream<T> generate(Supplier<T> s)
        Stream<Double> stream2 = Stream.generate(Math::random);
        stream2.limit(5).forEach(System.out::println); //输出前5个随机数
    }
}

3. Stream的中间操作

package com.java.stream;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值