StreamAPI
-
利用StreamAPI可以像流水线一样操作处理数据源(数组、集合……)
-
Stream自己不会存储元素
-
Stream不会改变数据源,而是会返回一个持有处理结构的新Stream
-
Steam操作时延迟执行的,他们会等到需要结果的时候才执行
- 称为惰性求值
Stream操作的三个步骤
-
创建Stream
- 一个数据源(如:集合、数组),获取一个流
-
中间操作
- 一个中间操作链,对数据源的数据进行处理
-
终止操作
- 一个终止操作,执行中间操作链,并产生结果
创建Stream
-
通过Collection系列集合提供的stream()或paralleStream()
-
List<String> list = new ArrayList<>(); Stream<String> stream = list.stream();
-
-
通过Arrays中的静态方法stream()获取数组流
-
Employee[] employees = new Employee[10]; Stream<Employee> stream1 = Arrays.stream(employees);
-
-
通过Stream类中的静态方法of()
-
Stream<String> stream2 = Stream.of("aa", "bb", "cc");
-
-
创建无限流
-
//1.迭代 //获取正偶数的无限流 Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2); stream3.limit(10).forEach(System.out::println); //2.生成 //获取随机数 Stream.generate(() -> Math.random()) .limit(5) .forEach(System.out::println);
-
中间操作
筛选与切片
-
filter——接收断言型Lambda,从流中排除某些元素
-
public void test1() { //过滤,保留年龄大于35的员工 employees.stream() .filter((e) -> { System.out.println("StreamAPI的中间操作"); return e.getAge() > 35; }) .forEach(System.out::println); }
-
-
limit——截断流,使其元素不超过给定数量
-
public void test2() { //截取,保留2个 employees.stream() .limit(2) .forEach(System.out::println); }
-
-
skip——跳过,扔掉前n个元素
-
public void test3() { //跳过,扔掉前2个 employees.stream() .skip(2) .forEach(System.out::println); }
-
-
distinct——去重,通过hashCode()和equals()判断是否相等
-
@Test public void test4() { //去重 employees.stream() .distinct() .forEach(System.out::println); }
-
映射
-
map——接受一个Lambda,将元素转换成其他形式或提取信息
-
接收一个函数作为参数,该函数会被应用到每个元素上,并映射成一个新的元素
-
public void test5() { List<String> list = Arrays.asList("aa", "bb", "ccc", "ddd", "eee"); list.stream() .map((s) -> s.toUpperCase()) .forEach(System.out::println); System.out.println("_________________"); employees.stream() .map(Employee::getName) .forEach(System.out::println); }
-
-
flatMap
-
接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流
-
public void test6() { List<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.stream() //返回值为Stream<Stream<Character>> .map(TestStreamAPI2::filterCharacter) .forEach((characterStream) -> { characterStream.forEach(System.out::println); }); System.out.println("------------------------"); list.stream() //返回值为Stream<Character> .flatMap(TestStreamAPI2::filterCharacter) .forEach(System.out::println); } public static Stream<Character> filterCharacter(String str) { List<Character> list = new ArrayList<>(); for(Character ch : str.toCharArray()) { list.add(ch); } return list.stream(); }
-
排序
-
sorted()——自然排序(Comparable)
-
sorted(Comparator cmp)——定制排序
-
public void test7() { List<String> list = Arrays.asList("bbb", "aaa", "ddd", "eee", "ccc"); list.stream() .sorted() .forEach(System.out::println); System.out.println("---------------------"); employees.stream() .sorted((e1, e2) -> { if(e1.getAge() == e2.getAge()) { return e1.getName().compareTo(e2.getName()); } else { return Integer.compare(e1.getAge(), e2.getAge()); } }) .forEach(System.out::println); }
终止操作
查找与匹配
-
allMatch——检查是否匹配所有元素
-
anyMatch——检查是狗至少匹配一个元素
-
noneMatch——检查是否没有匹配所有元素
-
findFirst——返回第一个元素
-
findAny——返回当前流中的任意元素
-
List<Employee> employees = Arrays.asList( new Employee("张三", 18, 9999.99, Employee.Status.FREE), new Employee("李四", 38, 5555.55, Employee.Status.BUSY), new Employee("王五", 50, 6666.66, Employee.Status.VOCATION), new Employee("赵六", 16, 3333.33, Employee.Status.FREE), new Employee("田七", 8, 7777.77, Employee.Status.BUSY) ); @Test public void test1() { boolean b1 = employees.stream() .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b1); boolean b2 = employees.stream() .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b2); boolean b3 = employees.stream() .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b3); Optional<Employee> first = employees.stream() .sorted(Comparator.comparingDouble(Employee::getSalary)) .findFirst(); System.out.println(first); Optional<Employee> any = employees.parallelStream() .filter((e) -> e.getStatus().equals(Employee.Status.BUSY)) .findAny(); System.out.println(any); }
-
-
count——返回流中元素的总个数
-
max——返回流中的最大值
-
min——返回流中的最小值
-
public void test2() { long count = employees.stream() .count(); System.out.println(count); Optional<Employee> max = employees.stream() .max(Comparator.comparingDouble(Employee::getSalary)); System.out.println(max); Optional<Double> min = employees.stream() .map(Employee::getSalary) .min(Double::compare); System.out.println(min); }
-
规约
-
reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
-
将流中的元素反复结合起来,得到一个值
-
identity代表一个初始值
-
public void test3() { 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); System.out.println("-------------------"); Optional<Double> op = employees.stream() .map(Employee::getSalary) .reduce(Double::sum); System.out.println(op.get()); }
-
收集
-
collect——将流转换为其他形式
-
接收一个Collector接口的实现
- 使用对应的静态类Collectors提供的静态方法,可以方便地创建Collector实例
-
用于给Stream中元素做汇总的方法
-
public void test4() { List<String> list = employees.stream() .map(Employee::getName) .collect(Collectors.toList()); list.forEach(System.out::println); System.out.println("------------------"); Set<String> set = employees.stream() .map(Employee::getName) .collect(Collectors.toSet()); set.forEach(System.out::println); System.out.println("------------------"); HashSet<Employee.Status> hashSet = employees.stream() .map(Employee::getStatus) .collect(Collectors.toCollection(HashSet::new)); hashSet.forEach(System.out::println); }
-
public void test5() { Double avg = employees.stream() .collect(Collectors.averagingDouble(Employee::getSalary)); System.out.println(avg); System.out.println("_________________________"); Double sum = employees.stream() .collect(Collectors.summingDouble(Employee::getSalary)); }
-
@Test public void test6() { // 分组 Map<Employee.Status, List<Employee>> collect = employees.stream() .collect(Collectors.groupingBy(Employee::getStatus)); System.out.println(collect); // 多级分组 Map<Employee.Status, Map<String, List<Employee>>> collect1 = employees.stream() .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> { if (e.getAge() <= 35) { return "青年"; } else if (e.getAge() <= 50) { return "中年"; } else { return "老年"; } }))); System.out.println(collect1); }
-
public void test7() { // 分区 Map<Boolean, List<Employee>> collect = employees.stream() .collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000)); System.out.println(collect); }
-
public void test8() { // 统计 DoubleSummaryStatistics statistics = employees.stream() .collect(Collectors.summarizingDouble(Employee::getSalary)); System.out.println(statistics.getSum()); System.out.println(statistics.getAverage()); System.out.println(statistics.getMax()); }
-
public void test9() { // 字符串处理 String collect = employees.stream() .map(Employee::getName) .collect(Collectors.joining(",", "===", "===")); System.out.println(collect); // ===张三,李四,王五,赵六,田七=== }
-
并行流与顺序流
-
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
-
底层使用到了Fork/Join框架
-
使用了工作窃取模式
-
将小任务分成了数个线程队列
-
当某个线程队列处理完成后,会从其他没有完成的线程队列末尾偷取任务
-
-
-
可以使用parallel方法将流切换到并行模式
-
提高工作效率