一、背景
lambda和stream是Java8中两个重要的新特性,lambda表达式和函数式接口的引入赋予java函数式编程的能力,该特性改变了传统的通过对象或匿名类调用接口方法的方式,可以将函数作为方法入参进行传递,极大的简化了代码复杂性,提高了代码可读性。
Stream 是Java8是对集合操作的一种补充,是处理集合的关键抽象概念。从功能来看,集合讲的是数据,流侧重的是计算。流可以执行复杂的查找、过滤和映射等数据操作,功能类似于使用 SQL 数据库查询语句。通过集合提供的数据操作接口,再配合Stream API使我们能够高效的进行各种场景的数据处理,提升编程效率,下面我们来介绍Stream API 的使用方法。
二 、API使用方法介绍
1.Stream<T> filter(Predicate<? super T> predicate);
接收一个Predicate函数,对stream中的每个元素执行Predicate函数的test方法,过滤出符合条件的元素,返回一个新的流对象。
Predicate<Student> studentPredicate = x -> x.getAge().intValue() > 20;
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Stream<Student> filterStream = studentStream.filter(studentPredicate);
2.<R> Stream<R> map(Function<? super T, ? extends R> mapper);
接收一个Function函数,对原始流中的每个元素执行apply方法,每个原始元素生成一个新的元素类型,最终生成一个流。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Function<Student,String> stringStudentFunction=x->x.getName();
Stream<String> names = studentStream.map(x->x.getName());
3.IntStream mapToInt(ToIntFunction<? super T> mapper);
接收ToIntFunction函数,对流程中的每个元素执行applyAsInt(T value)方法,生成一个int类型的元素,最终生成一个IntStream
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
ToIntFunction<Student> studentToIntFunction= x->x.getAge();
IntStream intStream=studentStream.mapToInt(studentToIntFunction);
4.LongStream mapToLong(ToLongFunction<? super T> mapper);
与IntStream mapToInt(ToIntFunction<? super T> mapper)接口类似。
5.DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
与IntStream mapToInt(ToIntFunction<? super T> mapper)接口类似。
6.<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
接收一个Function<? super T, ? extends Stream<? extends R>>对象,将原始流中的元素转换成一个流,针对每个元素生成的流重新组成一个新的流并返回。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Function<Student, Stream<String>> studentStreamFunction=x->Stream.of(x.getName());
Stream<String> stringStream=studentStream.flatMap(studentStreamFunction);
7.IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
接收一个(Function<? super T, ? extends IntStream>对象,该函数对象将原始流中的元素类型转换成IntStream,针对每个元素生成的IntStream形成一个新的IntStream 。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Function<Student, IntStream> studentIntStreamFunction=x->(IntStream) Stream.of(x.getAge());
IntStream intStream1=studentStream.flatMapToInt(studentIntStreamFunction);
8.LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
与IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper)类似
9.DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper)
与IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper)类似
10.Stream<T> distinct()
对原始流中的元素去重复,返回一个新流。
11.Stream<T> sorted();
对原始流中的元素进行排序。
12.Stream<T> sorted(Comparator<? super T> comparator)
接收Comparator<? super T>对象,对流中的元素按照compare(T o1, T o2)方法比较大小,返回一个排序流。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Comparator<Student> comparator =(x,y)-> x.getName().compareTo(y.getName());
studentStream.sorted(comparator);
13.Stream<T> peek(Consumer<? super T> action);
接收一个Consumer<? super T>对象,对流中的每个元素执行accept(T t)方法,返回一个新的流
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Consumer<Student> studentConsumer = x->x.setName("prefix"+x.getName());
studentStream.peek(studentConsumer);
14.Stream<T> limit(long maxSize);
返回一个长度不超过maxSize的新流。
15.Stream<T> skip(long n);
跳过n个元素,生成一个新流,配合Stream<T> limit(long maxSize)可以实现分页操作。
16.void forEach(Consumer<? super T> action);
接收一个Consumer<? super T>,对流中的元素执行accept(T t)操作,这是一个终端操作。
17.void forEachOrdered(Consumer<? super T> action);
功能与void forEach(Consumer<? super T> action)类似,区别在于,并行流中该方法能保持按顺序遍历并行流中的元素。
18.Object[] toArray();
返回一个Object类型的数组。
19.<A> A[] toArray(IntFunction<A[]> generator);
针对流中的每个元素,返回一个数组
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Student[] students = studentStream.toArray(Student[]::new);
20.T reduce(T identity, BinaryOperator<T> accumulator);
对流中的元素按照BinaryOperator<T> 提供的方法执行聚合操作,初始值是identity,返回聚合的结果。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
BinaryOperator<Integer> binaryOperator=( x,y)->x+y;
Integer result= studentStream.map(x->x.getAge()).reduce(0,binaryOperator);
21.Optional<T> reduce(BinaryOperator<T> accumulator);
对流中的元素按照BinaryOperator<T>提供的方法执行聚合操作,初始值默认为流中的第一个元素,返回一个Optional对象。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
BinaryOperator<Integer> binaryOperator=( x,y)->x+y;
Optional<Integer> optional = studentStream.map(x -> x.getAge()).reduce(binaryOperator);
22.<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
对流中的元素按照BinaryOperator<T> 提供的方法执行聚合操作,初始值是identity,使用BinaryOperator<U> 函数对象连接并行处理结果。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
BiFunction<Integer,Integer,Integer> biFunction=(x,y)->x+y;
BinaryOperator<Integer> integerBinaryOperator= (x,y)->x+y;
Integer result1 = studentStream.map(x -> x.getAge()).reduce(0,biFunction,integerBinaryOperator);
23.<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
使用Supplier<R>创建一个结果容器,使用BiConsumer<R, ? super T>生成结果容器的元素,并放入结果容器中,BiConsumer<R, R>处理并行流情况下多个线程产生的容器元素合并的问题。
示例一:
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Supplier<Map<String,List<Student>>> supplier=()->new HashMap<String,List<Student>>();
BiConsumer<Map<String,List<Student>>,Student> biConsumer= (x,y)->{
String key=y.getName();
if(x.containsKey(key)){
x.get(key).add(y);
}else{
x.put(key,Arrays.asList(y));
}
};
BiConsumer<Map<String,List<Student>>, Map<String,List<Student>>> combiner=(x,y)->x.putAll(y);
studentStream.collect(supplier,biConsumer,combiner);
示例二
Supplier<StringBuilder> supplier1=()->new StringBuilder();
BiConsumer<StringBuilder,String> biConsumer1=(x,y)->x.append(y);
BiConsumer<StringBuilder,StringBuilder> combiner1=(x,y)->x.append(y);
String concat = stringStream.collect(supplier1,biConsumer1,combiner1).toString();
24.<R, A> R collect(Collector<? super T, A, R> collector);
使用收集器Collector<? super T, A, R>对流中的元素执行可变规约操作,收集器封装了函数(Supplier, BiConsumer, BiConsumer),java sdk提供了Collector类,改类实现了常用收集器,具体请参考Collector类源码。
Stream<Student> studentStream = Stream.of(new Student("黎明", 24, 1), new Student("黄昏", 19, 2));
Function<Student, String> studentStringFunction = x -> x.getName();
Map<String, List<Student>> map = studentStream.collect(Collectors.groupingBy(studentStringFunction));
25.Optional<T> min(Comparator<? super T> comparator);
返回流中最小的元素。
Comparator<Student> comparator1=(x,y)->x.getAge().compareTo(y.getAge());
studentStream.min(comparator1);
26.Optional<T> max(Comparator<? super T> comparator);
返回流中最大的元素。
27.long count();
返回流中元素个数。
28.boolean anyMatch(Predicate<? super T> predicate);
流中元素是否有满足Predicate<? super T>函数的元素,有返回true
29.boolean allMatch(Predicate<? super T> predicate);
流中所有元素是否都满足Predicate<? super T>函数,是返回true
30.boolean noneMatch(Predicate<? super T> predicate);
流中所有元素是否都不满足Predicate<? super T>函数,是返回true
31.Optional<T> findFirst();
返回流中第一个元素
32.Optional<T> findAny();
返回流中一个元素。
33.static<T> Stream<T> of(T t)
返回包含一个T类型元素的流对象。
34.static<T> Stream<T> of(T... values)
返回包含多个T类型元素的流对象。
35.static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
将两个流拼接在一起。