Stream
是Java 1.8版本开始提供的一个接口,主要提供对数据集合使用流的方式进行操做,流中的元素不可变且只会被消费一次,全部方法都设计成支持链式调用。使用Stream API能够极大生产力,写出高效率、干净、简洁的代码。java
Stream
提供了静态构建方法,能够基于不一样的参数建立返回Stream实例
使用Collection
的子类实例调用stream()
或者parallelStream()
方法也能够获得Stream实例,两个方法的区别在于后续执行Stream
其余方法的时候是单线程仍是多线程数组
Stream<String> stringStream = Stream.of("1", "2", "3"); //无限长的偶数流 Stream<Integer> evenNumStream = Stream.iterate(0, n -> n + 2); List<String> strList = new ArrayList<>(); strList.add("1"); strList.add("2"); strList.add("3"); Stream<String> strStream = strList.stream(); Stream<String> strParallelStream = strList.parallelStream();
filter
方法用于根据指定的条件作过滤,返回符合条件的流多线程
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //得到只包含正数的流,positiveNumStream -> (1,2,3) Stream<Integer> positiveNumStream = numStream.filter(num -> num > 0);
map
方法用于将流中的每一个元素执行指定的转换逻辑,返回其余类型元素的流app
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //转换成字符串流 Stream<String> strStream = numStream.map(String::valueOf);
这三个方法是对map
方法的封装,返回的是官方为各个类型单独定义的Stream,该Stream还提供了适合各自类型的其余操做方法ide
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); IntStream intStream = stringStream.mapToInt(Integer::parseInt); LongStream longStream = stringStream.mapToLong(Long::parseLong); DoubleStream doubleStream = stringStream.mapToDouble(Double::parseDouble);
flatMap
方法用于将流中的每一个元素转换成其余类型元素的流,好比,当前有一个订单(Order)列表,每一个订单又包含多个商品(itemList),若是要获得全部订单的全部商品汇总,就可使用该方法,以下:this
Stream<Item> allItemStream = orderList.stream().flatMap(order -> order.itemList.stream());
这三个方法是对flatMap
方法的封装,返回的是官方为各个类型单独定义的Stream,使用方法同上线程
distinct
方法用于对流中的元素去重,判断元素是否重复使用的是equals
方法debug
Stream<Integer> numStream = Stream.of(-2, -1, 0, 0, 1, 2, 2, 3); //不重复的数字流,uniqueNumStream -> (-2, -1, 0, 1, 2, 3) Stream<Integer> uniqueNumStream = numStream.distinct();
sorted
有一个无参和一个有参的方法,用于对流中的元素进行排序。无参方法要求流中的元素必须实现Comparable
接口,否则会报java.lang.ClassCastException
异常设计
Stream<Integer> unorderedStream = Stream.of(5, 6, 32, 7, 27, 4); //按从小到大排序完成的流,orderedStream -> (4, 5, 6, 7, 27, 32) Stream<Integer> orderedStream = unorderedStream.sorted();
有参方法sorted(Comparator<? super T> comparator)
不须要元素实现Comparable
接口,经过指定的元素比较器对流内的元素进行排序code
Stream<String> unorderedStream = Stream.of("1234", "123", "12", "12345", "123456", "1"); //按字符串长度从小到大排序完成的流,orderedStream -> ("1", "12", "123", "1234", "12345", "123456") Stream<String> orderedStream = unorderedStream.sorted(Comparator.comparingInt(String::length));
peek
方法能够不调整元素顺序和数量的状况下消费每个元素,而后产生新的流,按文档上的说明,主要是用于对流执行的中间过程作debug的时候使用,由于Stream
使用的时候通常都是链式调用的,因此可能会执行屡次流操做,若是想看每一个元素在屡次流操做中间的流转状况,就可使用这个方法实现
Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList()); 输出: Filtered value: three Mapped value: THREE Filtered value: four Mapped value: FOUR
limit
方法会对流进行顺序截取,从第1个元素开始,保留最多maxSize
个元素
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); //截取前3个元素,subStringStream -> ("-2", "-1", "0") Stream<String> subStringStream = stringStream.limit(3);
skip
方法用于跳过前n个元素,若是流中的元素数量不足n,则返回一个空的流
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); //跳过前3个元素,subStringStream -> ("1", "2", "3") Stream<String> subStringStream = stringStream.skip(3);
forEach
方法的做用跟普通的for循环相似,不过这个能够支持多线程遍历,可是不保证遍历的顺序
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); //单线程遍历输出元素 stringStream.forEach(System.out::println); //多线程遍历输出元素 stringStream.parallel().forEach(System.out::println);
forEachOrdered
方法能够保证顺序遍历,好比这个流是从外部传进来的,而后在这以前调用过parallel
方法开启了多线程执行,就可使用这个方法保证单线程顺序遍历
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); //顺序遍历输出元素 stringStream.forEachOrdered(System.out::println); //多线程遍历输出元素,下面这行跟上面的执行结果是同样的 //stringStream.parallel().forEachOrdered(System.out::println);
toArray
有一个无参和一个有参的方法,无参方法用于把流中的元素转换成Object数组
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); Object[] objArray = stringStream.toArray();
有参方法toArray(IntFunction<A[]> generator)
支持把流中的元素转换成指定类型的元素数组
Stream<String> stringStream = Stream.of("-2", "-1", "0", "1", "2", "3"); String[] strArray = stringStream.toArray(String[]::new);
reduce
有三个重载方法,做用是对流内元素作累进操做
第一个reduce(BinaryOperator<T> accumulator)
accumulator
为累进操做的具体计算
单线程等下以下代码
boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element); } return foundAny ? Optional.of(result) : Optional.empty();
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //查找最小值 Optional<Integer> min = numStream.reduce(BinaryOperator.minBy(Integer::compareTo)); //输出 -2 System.out.println(min.get()); //过滤出大于5的元素流 numStream = Stream.of(-2, -1, 0, 1, 2, 3).filter(num -> num > 5); //查找最小值 min = numStream.reduce(BinaryOperator.minBy(Integer::compareTo)); //输出 Optional.empty System.out.println(min);
第二个reduce(T identity, BinaryOperator<T> accumulator)
identity
为累进操做的初始值accumulator
同上
单线程等价以下代码
T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //累加计算全部元素的和,sum=3 int sum = numStream.reduce(0, Integer::sum);
第三个reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
identity
和accumulator
同上combiner
用于多线程执行的状况下合并最终结果
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); int sum = numStream.parallel().reduce(0, (a, b) -> { System.out.println("accumulator执行:" + a + " + " + b); return a + b; }, (a, b) -> { System.out.println("combiner执行:" + a + " + " + b); return a + b; }); System.out.println("最终结果:"+sum); 输出: accumulator执行:0 + -1 accumulator执行:0 + 1 accumulator执行:0 + 0 accumulator执行:0 + 2 accumulator执行:0 + -2 accumulator执行:0 + 3 combiner执行:2 + 3 combiner执行:-1 + 0 combiner执行:1 + 5 combiner执行:-2 + -1 combiner执行:-3 + 6 最终结果:3
collect
有两个重载方法,主要做用是把流中的元素做为集合转换成其余Collection
的子类,其内部实现相似于前面的累进操做
第一个collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)
supplier
须要返回开始执行时的默认结果accumulator
用于累进计算用combiner
用于多线程合并结果
单线程执行等价于以下代码
R result = supplier.get(); for (T element : this stream) accumulator.accept(result, element); return result;
第二个collect(Collector<? super T, A, R> collector)
collector
实际上是对上面的方法参数的一个封装,内部执行逻辑是同样的,只不过JDK提供了一些默认的Collector
实现
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); List<Integer> numList = numStream.collect(Collectors.toList()); Set<Integer> numSet = numStream.collect(Collectors.toSet());
min
方法用于计算流内元素的最小值
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); Optional<Integer> min = numStream.min(Integer::compareTo);
min
方法用于计算流内元素的最大值
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); Optional<Integer> max = numStream.max(Integer::compareTo);
count
方法用于统计流内元素的总个数
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //count=6 long count = numStream.count();
anyMatch
方法用于匹配校验流内元素是否有符合指定条件的元素
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //判断是否包含正数,hasPositiveNum=true boolean hasPositiveNum = numStream.anyMatch(num -> num > 0);
allMatch
方法用于匹配校验流内元素是否全部元素都符合指定条件
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //判断是否所有是正数,allNumPositive=false boolean allNumPositive = numStream.allMatch(num -> num > 0);
noneMatch
方法用于匹配校验流内元素是否都不符合指定条件
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //判断是否没有小于0的元素,noNegativeNum=false boolean noNegativeNum = numStream.noneMatch(num -> num < 0);
findFirst
方法用于获取第一个元素,若是流是空的,则返回Optional.empty
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); //获取第一个元素,firstNum=-2 Optional<Integer> firstNum = numStream.findFirst();
findAny
方法用于获取流中的任意一个元素,若是流是空的,则返回Optional.empty,由于可能会使用多线程,因此不保证每次返回的是同一个元素
Stream<Integer> numStream = Stream.of(-2, -1, 0, 1, 2, 3); Optional<Integer> anyNum = numStream.findAny();