在Java 8 中,stream是新增的一大亮点,Stream 是对集合对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。它像是一种是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,流本身不是一种数据结构,不能够存储数据,它只关注于数据内部的计算,在一定程度上类似于迭代器,单向运行,只能使用一次,但是与之不同的是Stream能够并行化操作。简单来说:集合专注于数据,而流专注于计算
(1)、创建Stream
一个数据源(如:集合、数组),获取一个流
(2)、中间操作
一个中间操作链,对数据源的数据进行处理
(3)、终止操作
一个终止操作,执行中间操作链,并产生结果。
创建Stream的方式有多种
default Stream<E> stream() : 返回一个顺序流
default Stream<E> parallelStream() : 返回一个并行流
List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); //获取一个顺序流 Stream<String> parallelStream = list.parallelStream(); //获取一个并行流static <T> Stream<T> stream(T[] array)
Integer[] nums = new Integer[10]; Stream<Integer> stream1 = Arrays.stream(nums);public static<T> Stream<T> of(T... values)
Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) 生成 public static<T> Stream<T> generate(Supplier<T> s)
//迭代,生成偶数集合无限流 Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2) //生成随机数 Stream<Double> stream4 = Stream.generate(Math::random);多个 中间操作 可以连接起来形成一个流水线,除非流水 线上触发终止操作,否则中间操作不会执行任何的处理! 而在终止操作时一次性全部处理,称为“惰性求值”。
终端操作会从流的流水线生成结果。其结果可以是任何不是流的 值,例如:List、Integer,甚至是 void
流进行了终止操作后,不能再次使用
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态 方法,可以方便地创建常见收集器实例
List<Integer> list = emps.stream() .map(Employee::getAge) .collect(Collectors.toList()); list.forEach(e-> System.out.println(e)); Set<Integer> set = emps.stream() .map(Employee::getAge) .collect(Collectors.toSet()); set.forEach(e-> System.out.println(e)); HashSet<Integer> map = emps.stream() .map(Employee::getAge) .collect(Collectors.toCollection(HashSet::new)); map.forEach(e-> System.out.println(e)); Optional<Double> max = emps.stream() .map(Employee::getSalary) .collect(Collectors.maxBy(Double::compare)); System.out.println("员工工资最高:"+max.get()); Optional<Employee> op = emps.stream() .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))); System.out.println("员工工资最低:"+op.get()); Map<String, List<Employee>> name = emps.stream().collect(Collectors.groupingBy(e -> e.getName())); System.out.println("按名分组"+name); Map<String, Map<Double, List<Employee>>> names = emps.stream(). collect(Collectors.groupingBy(e -> e.getName(), Collectors.groupingBy(f -> f.getSalary()))); System.out.println("多级分组,先按名,再按工资"+names); Map<Boolean, List<Employee>> collect = emps.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 7000)); System.out.println("分区:"+collect);