Java中的Stream是一种用于处理集合(数组、列表等)和其他数据源的元素序列的抽象。Stream API提供了一种声明性的编程风格,可以方便地对数据进行过滤、映射、聚合等操作。
Stream是Java8API添加的一个新的抽象,称为流Stream,以一种声明性方式处理数据集合(侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式)
Stream流是从支持数据处理操作的源生成的元素序列,源可以是数组、文件、集合、函数。流不是集合元素,它不是数据结构并不保存数据,它的主要目的在于计算
特点
1、代码简洁:函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环
2、多核友好:Java函数式编程使得编写并行程序如此简单,就是调用一下方法
接口继承关系
BaseStream:基础接口,声明了流管理的核心方法;
Stream:核心接口,声明了流操作的核心方法,其他接口为指定类型的适配
1. 创建流:可以通过调用集合或数组的stream()方法来创建一个Stream对象,
例如:
- 集合流:List<String> list = new ArrayList<>(); Stream<String> stream = list.stream();
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
integerList.add(4);
integerList.add(5);
Stream<Integer> listStream = integerList.stream();
- 数组流:String[] array = new String[]{"a", "b", "c"}; Stream<String> stream = Arrays.stream(array);
int[] intArr = {1, 2, 3, 4, 5};
IntStream arrayStream = Arrays.stream(intArr);
2.中间操作
通常对于Stream的中间操作,可以视为是源的查询,并且是懒惰式的设计,对于源数据进行的计算只有在需要时才会被执行,与数据库中视图的原理相似;
Stream流的强大之处便是在于提供了丰富的中间操作,相比集合或数组这类容器,极大的简化源数据的计算复杂度
一个流可以跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用
这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的filter、map等
- filter(Predicate<T> predicate):根据条件过滤元素;
- map(Function<T, R> mapper):对元素进行映射转换;
- distinct():去除重复的元素;
- sorted():对元素进行排序;
- limit(long maxSize):限制元素的数量;
- skip(long n):跳过指定数量的元素。
3. 终端操作:终端操作是对流进行最终处理并产生结果的操作。常用的终端操作包括:
- forEach(Consumer<T> action):对每个元素执行指定操作;
- collect(Collector<T, A, R> collector):将流中的元素收集到一个集合中;
- count():统计流中的元素个数;
- reduce(BinaryOperator<T> accumulator):对流中的元素进行归约操作,返回一个Optional对象。
通过使用Stream,可以简化对集合的操作,提高代码的可读性和维护性。但需要注意,Stream是一次性的,一旦对流进行终端操作后就不能再使用了。