• java8(一)Stream API


    Stream API

    Stream API – > java.util.stream
    Stream是java8中处理集合的关键抽象概念
    可以执行非常复杂的查找、过滤和映射数据等操作
    类似于使用SQL执行的数据库查询
    Stream API提供了一种高效且易于使用的数据处理方式

    Stream和Collection的区别

    Collection是一种静态的内存数据,主要面向内存,存储在内存中
    Stream与计算有关,主要面向CPU,通过CPU实现计算

    注意:

    1. Stream 自己不会存储元素
    2. Stream 不会改变源对象。会返回一个持有结果的新Stream
    3. Stream 操作时延迟执行的,需要结果的时候才执行

    Stream操作的三个步骤

    1. 创建Stream
      使用一个数据源(如:集合、数组),获取一个Stream流
    2. 中间操作(过滤、映射…)
      中间操作链,对数据源进行数据加工处理
    3. 终止操作(终端操作)
      一点执行终止操作,就执行中间操作链,并返回结果。之后,不会再被使用

    创建Stream

    方法一:通过集合创建

    1. 顺序流:按照集合中的顺序进行执行
    // default Stream<E> stream();
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<Employee> stream = employees.stream();
    
    • 1
    • 2
    • 3
    1. 并行流
    // default Stream<E> parallelStream()
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<Employee> parallelStream = employees.parallelStream();
    
    • 1
    • 2
    • 3

    方法二:通过数组创建

    // Arrays static <T> Stream<T> stream(T[] array)
    Employee[] empArr = employees.toArray(new Employee[employees.size()]);
    Stream<Employee> stream1 = Arrays.stream(empArr);
    int[] iArr = {1,2,3};
    IntStream intStream = Arrays.stream(iArr);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    通过Stream类的静态方法 of创建

    // static<T> Stream<T> of(T... values);
    Stream<String> stringStream = Stream.of("1", "2", "3", "4");
    Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
    
    • 1
    • 2
    • 3

    方式四:无限流

    1. 迭代:public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
    2. 生成:public static<T> Stream<T> generate(Supplier<T> s)
    Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
    Stream.generate(Math::random).limit(10).forEach(System.out::println);
    
    • 1
    • 2

    中间操作

    多个中间操作可以链接起形成一条,除非链上触发终止操作,否则中间操作不会执行任何处理,只有在终止操作时一次性全部处理,称为惰性求值

    筛选与切片

    方法描述
    filter(Predicate p)接收Lambda,从流中排出某些元素
    distinct()筛选,通过流所生成元素的hashCode()equals()去除重复元素
    limit(long maxSize)截断流,使元素不超过给定数量
    skip(long n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(long maxSize)互补
    // filter(Predicate p) 接收Lambda,从流中排出某些元素
    List<Employee> list = EmployeeData.getEmployees();
    Stream<Employee> stream = list.stream();
    // 查询员工薪资大于90000
    stream.filter(e -> e.getSalary() > 90000).forEach(System.out::println);
    System.out.println("******************************************************");
    stream = list.stream();
    // limit(long maxSize) 截断流,使元素不超过给定数量
    stream.limit(3).forEach(System.out::println);
    System.out.println("******************************************************");
    // skip(long n) 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与 limit(long maxSize) 互补
    list.stream().skip(5).forEach(System.out::println);
    System.out.println("******************************************************");
    // distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
    list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
    list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
    list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
    list.stream().distinct().forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    映射

    方法描述
    map(Function f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素
    mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的DoubleStream
    mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的IntStream
    mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的LongStream
    flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
    // 中间操作:映射
    @Test
    public void test3() {
        // map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素
        List<String> list = Arrays.asList(new String[]{"tom", "jerry"});
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
    
        List<Employee> employeeList = EmployeeData.getEmployees();
        employeeList.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);
    
    
        System.out.println("########################################S");
        // flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
        list.stream().map(StreamAPITest::stringToStream).forEach(s -> {
            s.forEach(System.out::println);
        });
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        list.stream().flatMap(StreamAPITest::stringToStream).forEach(System.out::println);
    }
    
    public static Stream<Character> stringToStream(String str) {
        List<Character> list = new ArrayList<>();
        for (char c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    排序

    方法描述
    sorted()自然排序
    sorted(Comparator com)按比较强顺序排序
    // sorted() 自然排序
    List<Integer> intList = Arrays.asList(2, 6, 2, 1, 7, 12, 45, 67);
    intList.stream().sorted().forEach(System.out::println);
    System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
    
    // sorted(Comparator com) 按比较强顺序排序
    List<Employee> list = EmployeeData.getEmployees();
    list.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    终止操作

    会使流产生结果,其中的结果可以是任何不是流的值,如:List,Integer,void。流进行终止操作后,不能再次使用

    匹配与查找

    方法描述
    allMatch(Predicate p)检查是否匹配到所有元素
    anyMatch(Predicate p)检查是否匹配到至少一个元素
    noneMatch(Predicate p)检查是否没有匹配到所有元素
    findFirst()返回第一个元素
    findAny()返回当前流中的任意元素
    count()返回流中元素总数
    max(Comparator c)返回流中最大值
    min(Comparator c)返回流中最小值
    forEach(Consumer c)内部迭代 ,使用Collection接口需要yoghurt去做的迭代叫外部迭代,StreamAPI使用内部迭代。也可以用Collection.forEach(Consumer c)做迭代
    // 匹配与查找
    @Test
    public void test1() {
        // | allMatch(Predicate p) | 检查是否匹配到所有元素 |
        List<Employee> list = EmployeeData.getEmployees();
        boolean b = list.stream().allMatch(e -> e.getAge() >= 30);
        System.out.println(b);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | anyMatch(Predicate p) | 检查是否匹配到至少一个元素 |
        boolean b1 = list.stream().anyMatch(e -> e.getSalary() > 50000);
        System.out.println(b1);
        System.out.println("####################################################");
        // | noneMatch(Predicate p) | 检查是否没有匹配到所有元素 |
        boolean b2 = list.stream().noneMatch(e -> e.getName().contains("马"));
        System.out.println(b2);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@S");
        // | findFirst() | 返回第一个元素 |
        Optional<Employee> firstEmployee = list.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
        System.out.println(firstEmployee);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | findAny() | 返回当前流中的任意元素 |
        Optional<Employee> anyEmployee = list.parallelStream().findAny();
        System.out.println(anyEmployee);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | count() | 返回流中元素总数 |
        long count = list.stream().count();
        System.out.println(count);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | max(Comparator c) | 返回流中最大值 | 注意,比较方法写反了,取得最小值
        // Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e2.getSalary(), e1.getSalary()));
        Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("max:" + max);
        Optional<Double> maxSalary = list.stream().map(Employee::getSalary).max(Double::compare);
        System.out.println("maxSalary:" + maxSalary);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | min(Comparator c) | 返回流中最小值 |
        Optional<Employee> min = list.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        // | forEach(Consumer c) | 内部迭代 |
        list.stream().forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    归约

    方法描述
    reduce(T iden, BunaryOperator b)可以将流中元素反复结合起来,得到一个值。返回T
    reduce(BinaryOperator b)将流中元素反复结合,得到一个值。返回Optional<T>

    **备注:**map和reduce的连接通常称为map-reduce模式,因Google用它来进行网络搜索而出名

    // 归约
    @Test
    public void test3() {
        // | reduce(T iden, BunaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer reduce = list.stream().reduce(0, Integer::sum);
        System.out.println(reduce);
        // | reduce(BinaryOperator b) | 将流中元素反复结合,得到一个值。返回Optional\<T> |
        List<Employee> employeeList = EmployeeData.getEmployees();
        Optional<Double> reduce1 = employeeList.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(reduce1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    收集

    方法描述
    collect(Collector c)将流转换为其他形式。接收一个Collector接口的实现

    Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)

    Collectors实现类提供了很多的静态方法,可以方便地创建常见收集器实例,方法见下表:

    方法返回类型作用示例
    toListList<T>把流中元素收集到Listlist.stream().collect(Collectors.toList())
    toSetSet<T>把流中元素收集到Setlist.stream().collect(Collectors.toSet())
    toCollectionCollection<T>把流中元素收集到创建的集合list.stream().collect(Collectors.toCollection(ArrayList::new))
    countingLong计算流中元素个数list.stream().collect(Collectors.counting())
    summingIntInteger对流中元素整数属性进行求和list.stream().collect(Collectors.summingInt(Employee::getSalary))
    averagingIntInteger对流中Integer属性求平均值list.stream().collect(Collectors.averagingInt(Employee::getAge))
    summarizingIntIntSummaryStatics收集流中Integer属性的统计值。如平均值list.stream().collect(Collectors.summarizingInt(Employee::getAge))
    joiningString连接流中每个字符串list.stream().collect(Collectors.joining())
    maxByOptional<T>根据比较器获取最大值list.stream().collect(Collectors.maxBy(Employee::getSalary))
    minByOptional<T>根据比较器获取最小值list.stream().collect(Collectors.minBy(Employee::getSalary))
    reducing归约产生的类型从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值list.stream().collect(Collectors.reducing(0, Employee::getSalary, Integer::sum))
    collectIngAndThen转换函数返回的类型包裹另一个收集器,对其结果转换函数list.stream().collect(Collectors.collectIngAndThen(Collectors.toList(), List::size))
    groupingByMap<k, List<T>>根据某属性值对流分组,属性为K,结果为Vlist.stream().collect(Collectors.groupingBy(Employee::getStatus)
    partitioningByMap<Boolean, List<T>>根据true或false进行分区list.stream().collect(Collectors.partitioningBy(Employee::getManage)
    // 收集
    @Test
    public void test4() {
        // | collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现 |
        List<Employee> list = EmployeeData.getEmployees();
        List<Employee> collect = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toList());
        System.out.println(collect);
        System.out.println();
        // | toSet | Set\<T> | 把流中元素收集到Set| list.stream().collect(Collectors.toSet()) |
        Set<Employee> collect1 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toSet());
        System.out.println(collect1);
        System.out.println();
        // | toCollection | Collection\<T> | 把流中元素收集到创建的集合| list.stream().collect(Collectors.toCollection(ArrayList::new)) |
        ArrayDeque<Employee> collect2 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toCollection(ArrayDeque::new));
        System.out.println(collect2);
        System.out.println();
        // | counting | Long | 计算流中元素个数 | list.stream().collect(Collectors.counting()) |
        Long collect3 = list.stream().collect(Collectors.counting());
        System.out.println(collect3);
        // | summingInt | Integer | 对流中元素整数属性进行求和|list.stream().collect(Collectors.summingInt(Employee::getSalary)) |
        Integer collect4 = list.stream().collect(Collectors.summingInt(Employee::getAge));
        System.out.println(collect4);
        IntSummaryStatistics collect5 = list.stream().collect(Collectors.summarizingInt(Employee::getAge));
        System.out.println("collect5:" + collect5);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    openEuler 服务器安装 JumpServer (all-in-one 模式)
    SD-WAN专线:一带一路市场布局的商业加速器
    Java并发-为什么主线程结束了,程序却没有关闭呢?
    Redis学习(九)SpringBoot实现(Pub/Sub)发布订阅
    PHP 免费开源 cms 内容管理系统 (07flyCMS)
    pytorch:图像识别模型与自适应策略
    Azure DevOps和Jira比较
    flask旅游景点推荐
    微调stable diffusion哪个部分才是最有效的?
    Opengl之面剔除
  • 原文地址:https://blog.csdn.net/qq_29107721/article/details/125381557