一、概述
Stream 关注的是对数据的运算,与CPU打交道;集合关注的是数据的存储,与内存打交道
- Stream自己不会存储数据
- Stream不会改变源数据,相反,他们会返回一个持有结果的新Stream
- Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才执行
步骤:
- 创建Stream,一个数据源(如:集合,数组),获取一个流
- 中间操作,一个中间操作链,对数据源的数据进行处理
- 终止操作,一旦执行终止操作,就执行中间操作链,并产生结果,之后,不会再被使用
二、创建Strem
1.通过集合
Java8中的Collection接口有stream,paralleStream方法:
- default Stream<E> stream() 返回一个顺序流
- default Stream<E> paralleStream() 返回一个并行流
@Test
public void test11() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Stream<Integer> stream = list.stream();
Stream<Integer> integerStream = list.parallelStream();
}
2.通过数组
Arrays有静态方法stream()可以获取数组流:
- public static IntStream stream(int[] array)
- public static LongStream stream(long[] array)
- public static DoubleStream stream(double[] array)
@Test
public void test12() {
int[] arr = new int[] {1, 2, 3};
IntStream intStream = Arrays.stream(arr);
}
3.通过Stream的of()
Stream类有静态方法of()可以获取一个流
- public static<T> Stream<T> of(T... values)
@Test
public void test13() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
}
4.创建无限流
可以使用静态方法Stream.iterate()和Stream.generate()创建无限流
- public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- public static<T> Stream<T> generate(Supplier<T> s)
@Test
public void test14() {
Stream<Integer> iterate = Stream.iterate(0, t -> t + 2);
Stream<Double> generate = Stream.generate(Math::random);
}
三、Stream的中间操作
1.筛选与切片
- filter(Predicate p) 接受Lambda,从流中筛选某些元素
- distinct() 通过流生成元素的hashCode()和equals()去除重复元素
- limit(long maxSize) 截断流,使其元素不超过给定数量
- skip(long n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
@Test
public void test21() {
List<String> list = Arrays.asList("C", "A", "A", "B");
// 1.filter
Stream<String> stream = list.stream();
stream.filter((s) -> s.equals("A")).forEach(System.out::print);
System.out.println();
// 2.distinct
stream = list.stream();
stream.distinct().forEach(System.out::print);
System.out.println();
// 3.limit
stream = list.stream();
stream.limit(2).forEach(System.out:: print);
System.out.println();
// 4.skip
stream = list.stream();
stream.skip(2).forEach(System.out::print);
System.out.println();
}
结果:
2.映射
- map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
- mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream
- mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream
- mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream
- flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
@Test
public void test22() {
List<String> list = Arrays.asList("C", "A", "A", "B");
list.stream().map(str -> str.toLowerCase()).forEach(System.out::print);
}
结果:
3.排序
- sorted() 产生一个新流,其中按自然顺序排序
- sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
@Test
public void test23() {
List<String> list = Arrays.asList("C", "A", "A", "B");
list.stream().sorted().forEach(System.out::print);
}
结果:
四、Stream的终止操作
1.匹配与查找
- allMatch(Predicate p) 检查是否匹配所有元素
- anyMatch(Predicate p) 检查是否至少匹配一个元素
- noneMatch(Predicate p) 检查是否没有匹配所有元素
- findFirst() 返回第一个元素
- findAny() 返回当前流中的任意元素
- count() 返回流中元素总数
- max(Comparator c) 返回流中最大值
- min(Comparator c) 返回流中最小值
- forEach(Consumer c) 内部迭代(使用Collection接口需要用户去做迭代,称为外部迭代,相反,Stream API使用内部迭代--它帮你把迭代做了)
@Test
public void test31() {
List<String> list = Arrays.asList("C", "A", "A", "B");
boolean allMatch = list.stream().allMatch(e -> e.equals("B"));
System.out.println(allMatch);
boolean anyMatch = list.stream().anyMatch(e -> e.equals("B"));
System.out.println(anyMatch);
}
结果:
2.归约
- reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回T
- reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回Optional<T>
@Test
public void test32() {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println(sum);
}
结果:
3.收集
Colletor接口中方法的实现决定了如何对流执行收集的操作(如收集到List,Set,Map)
Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例
- collect(Collector c) 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
@Test
public void test33() {
List<String> list = Arrays.asList("C", "A", "A", "B");
List<String> resList = list.stream().filter(e -> e.equals("A")).collect(Collectors.toList());
System.out.println(resList);
}
结果: