尚硅谷_初级_java8 新特性(666-)

https://www.bilibili.com/video/BV1Kb411W75N?p=666
大处着眼,小处着手。
一:前面:
   1.接口增强:可以写 default 方法,静态方法。
      默认方法:由子类的对象调用,子类可以重写。
      静态方法:由父类.静态方法名 调用,子类不能重写,子类对象不能调用。
   2.提供新的 时间 和 日期 API。
   3.注解:
      类型注解:
      重复注解:
   4.容器底层变化:集合和map。
   5.Java 8 最大的两个改变:
      Lambda 表达式 和 Stream API。
二:Lambda 表达式(使代码更简洁)
   1. lambda介绍:
      lambda 是一个匿名函数,我们可以将 Lambda 表达式,理解为是一段可以传递的代码,
      (将代码像数据一样传递)。使用它,可以写出更简洁,更灵活的代码。
   2.将来大数据 spark 底层有使用,java8 新特性,比如 Lambda 表达式。
   3.举例:
      1) 普通写法:
            Runnable runnable = new Runnable() {
                                       @Override
                   public void run() {
                  System.out.println("我爱北京*,");
                   }                *           };
         Lambda表达式:
            Runnable runnable = () -> System.out.println("123");
      2)
   4.解释 lambda 表达式:
      1)->:Lambda 操作符/箭头操作符
      2) 左边:Lambda 形参列表
               接口中,抽象方法的形参。其实就是,接口中,抽象方法的形参列表。
         右边:Lambda 体:
               接口中,抽象方法的方法体。其实就是 抽象方法的 方法体。
      3)以前用,匿名实现类 表示的方式 ,现在都可以用 Lambda 表达式来写。
      4)Lambda 表达式,就是一个函数式接口的实例。
   5.Lambda 表达式分类(6)
      1)无参 无返回值:Runnable runnable = () -> System.out.println("123");
      2)有参 无返回值:
            Runnable runnable = (String str) -> {
                                          sout("123");
                                                   }
      3)数据类型可以省略,因为可以由编译器 推断得出,称为 “类型推断”
            COnsumer<String> con2 = (s) ->     {
                                       sout("123");
                                               }
      4)Lambda 表达式,若只需要一个参数,参数的小括号可以省略:
            COnsumer<String> con2 =   s ->     {
                                       sout("123");
                                               }
      5)Lambda 表达式,需要两个或者以上的参数,多条语句执行,可以有返回值
            Comparator<Integer> com = (x,y) -> {
                                          sout("123");
                                          return x+y;
                                                   };
      6)Lambda 体只有一条语句时,return 或 大括号 都可以可以省略:
            Runnable runnable = () -> System.out.println("123");
   6.Lambda 表达式 本质:
      作为 函数式 接口的实例,
      函数时接口的特点就是,只有一个抽象方法。
三:函数式(Functional)接口(Interface)
   1.如果一个接口中,只包含 一个抽象方法,此接口,就称为,函数式接口。
   2.可以通过 Lambda 表达式,创建 函数式接口 的对象。
   3.@FunctionalInterface 注解 :接口上标注,说明此接口,是函数事接口,
      不是函数式接口,报错,也可以起到检验是否是函数式接口的作用。
   4.Java 内置 ,四大核心 函数式接口:
                     参数类型   返回类型      用途
      1)COnsumer<T>        T       void    void accep(T t)。对类型为 T 的对象 应用操作,包含方法:
         消费型接口
      2)Supplier<T>        无        T     T get()。返回类型为 T 类型,包含方法
         供给型接口
      3)Function<T,R>       T        R     R apple(T t)。对 类型 T 的对象应用操作,并返回 R 类型对象
         函数型接口
      4)Predicate<T>       T         Boolean       boolean test(T t)。确定类型为 T 的对象,是否满足约束,
         断定型接口
四:方法引用 与 构造器引用(用于替换 Lambda 表达式)
   1.方法引用
      1)方法引用举例:
         1.Lambda表达式 表示:
            Comparator<Integer> comparator1 = (o1, o2) -> Integer.compare(o1, o2);
         2.方法引用 表示:
            Comparator<Integer> comparator2 = Integer::compareTo;
      2)方法引用使用场景:
         当要传递给 Lambda体 的操作,已经有实现的方法了,可以使用方法引用。
         方法引用,可以看做是,Lambda 表达式,更深层次的表达。
         换句话说:方法引用本质 就是 Lambda 表达式,也就是函数式接口的一个实例。
      3)使用格式:
         通过 方法的名字,来指向一个方法,可以认为是 Lambda 表达式 的一个语法糖。
         类/对象  ::  方法名
      4)具体分为 三种情况
         1.对象  ::  非静态方法
         2.类  ::  静态方法
         3.类  ::  非静态方法
      5)使用场景要求:
         1.要求接口中的,抽象方法的 形参列表 和 返回值类型,
             与 方法引用的 方法的 形参列表 和 返回值类型相同。
   2.构造器引用
      1)构造器引用举例:
         1.Lambda表达式 表示:
            Supplier<Employee> employeeSupplier = () -> new Employee();
         2.方法引用 表示:
            Supplier<Employee> employeeSupplier1 = Employee::new;
      2)要求:
         和方法引用类似,函数式接口的 抽象方法的 形参列表 和 构造器 形参列表一致,
            抽象方法的返回值类型 即为 构造器 所属的类的类型。
   3.数组引用:
五:强大的 Stream API(对内存中数据操作)
   0.介绍
      1)并行流:
         就是将一个内容,分成多个数据块,并用不同的线程,分别处理
         每个数据块的流。
         相比于串行流,并行流可以很大程度上提高程序的执行效率。
      2)串行流:
   1.Stream 介绍
      1) java 8 重要的改变,Stream API 真正的把 函数式编程风格,引入到java 中,
         简化了对集合的操作,可以执行复杂的 查找、过滤 和 映射数据 等操作。
      2)为什么使用 Stream API:?
         实际开发中,项目中多数数据源都来自 mysql,oracle等数据库,
         但现在,数据源更多了,有 MongDB,Redis等,而这些,NoSQL 的数据,
         就需要java 层面来处理了。
      3)Stream 和 Collection 区别:
         Collection :
            是一种 静态的内存数据结构,主要是对数据的存储。
            主要是面向内存,存储到内存中。
         而 Stream  :(数据渠道)
            是有关计算的,用于操作数据源 所生成的 元素序列。
            主要面向 CPU,通过 CPU 计算实现。
      4)注意:
         1.Stream 不会自己存储数据
         2.Stream 不会改变源对象。相反,他们会返回一个,持有结果的新 Stream
         3.Stream 操作是延迟执行的。这意味着,他们会等到需要结果的时候,才运行。
   2.Stream 操作有三个步骤:
      1)创建 Stream:
         根据 数据源(如:集合,数组),获取一个 对应的流。
      2)中间操作:
         一个中间操作链,对数据源的数据,进行处理。
      3)终止操作(终端操作)
         一旦执行 终止操作,才会执行 中间操作链 ,并产生结果,之后不会在被使用。
   3.Stream 创建对象操作(4)
      1)通过集合创建:
         //1.通过集合创建 Stream
            List<Employee> employees = EmployeeData.getEmployees();
         //顺序流:根据集合,获取一个顺序流,按照集合中顺序来
            Stream<Employee> stream = employees.stream();
         //并行流:根据集合,获取一个并行流,集合中并行取数据
            Stream<Employee> employeeStream = employees.parallelStream();
      2) //通过数组创建 Stream
            int[] a = new int[]{21321,323,323,2323,232,332,3,23,2,3,2};
            IntStream stream = Arrays.stream(a);
      3) //通过 Stream 的 of
            Stream<Integer> integerStream = Stream.of(1, 2, 32, 32, 34);
            Stream<String> fdsf = Stream.of("fdsf", "afdsf", "sadf");
      4) //创建无限流,可以造数据。
         //迭代:遍历 前十个 偶数
            Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
         //生成:
            Stream.generate(Math::random).limit(10).forEach(System.out::println);
   4.Stream 的中间操作(3):多个中间操作,可以连接起来一个链,形成一个流水线。
      1)筛选与切片
         1.过滤:filter(Predicate p):接收Lambda,从流中排除数据
            List<Employee> employees = EmployeeData.getEmployees();
            Stream<Employee> stream = employees.stream();
            //从流中,筛选出 年龄 大于 10 的数据
            stream.filter(e -> e.getAge() > 10).forEach(System.out::println);
         2.limit(int a):截断流,使其元素不会超过给定数量
            Stream<Employee> stream1 = employees.stream();
            stream1.limit(2).filter(e->e.getAge()>10).forEach(System.out::println);
         3.skip(n):跳过元素,返回一个扔掉了,前 n 个元素的流。若超过,返回空
            Stream<Employee> stream2 = employees.stream();
            stream2.skip(30).forEach(System.out::println);
         4.distinct():筛选,通过流 所生成元素的 hashcode() 和 equals() 去除重复元素
            Stream<Employee> stream3 = employees.stream();
            stream3.distinct().forEach(System.out::println);
      2)映射:
         1.Map(Function f):接收一个函数,作为参数,将元素转换成 其他形式或提取信息,
               该函数,将会被应用到 每个元素上,并将其映射成一个新的元素。
               可以 将 list 里面的元素,挑选出来,转换为list<元素>的集合。
            //将 list 里面字母,转换为大写
               List<String> strings = Arrays.asList("fasdf", "dsf", "fdsd");
               Stream<String> stream = strings.stream();
               stream.map(str -> str.toUpperCase()).forEach(System.out::println);
            //获取员工姓名大于 3 的员工
               List<Employee> employees = EmployeeData.getEmployees();
               Stream<Employee> stream1 = employees.stream();
               Stream<String> stringStream = stream1.map(e -> e.getName());
               stringStream.forEach(System.out::println);
               Stream<String> stringStream1 = stringStream.filter(name -> name.length() > 3);
         2.flatMap(Function f):接收一个函数作为参数,将流中的每个值,都换成另一个流。
               然后把,所有流,连成一个流。
            1)
            2)
            3)
      3)排序:
         1.sorted():
            1)产生一个 新流,其中 按照自然顺序 排序。
            2)示例:
               List<Integer> integers = Arrays.asList(123, 23122, 3, 123);
               Stream<Integer> stream = integers.stream();
               Stream<Integer> sorted = stream.sorted();
               sorted.forEach(System.out::println);
         2.sorted(Comparaotr com):
            1)产生一个新流,其中按比较器 顺序排序。
            2)示例:
               List<Employee> employees = EmployeeData.getEmployees();
               Stream<Employee> sorted =
                     employees.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
               sorted.forEach(System.out::println);
            3)如果排序相同,可以按照第二个字段排序:
               int a = Integer.compare(e1.getAge(), e2.getAge());
               if (a != 0) {
                  return a;
                   } else {
                  return Integer.compare(e1.getAge(),e2.getAge());
                   }
   5.终止操作:
      1)匹配与查找:
         1.判断是否都
            //判断 流 里的对象的 年龄 是否都大于 18 岁
            List<Employee> employees = EmployeeData.getEmployees();
            Stream<Employee> stream = employees.stream();
            boolean b = stream.allMatch(e -> e.getAge() > 200);
            System.out.println(b);
         2.检查是否至少匹配一个(查看是否存在)
            //判断 是否讯在 年龄 小于 33
            boolean b1 = stream.anyMatch(e -> e.getAge() < 33);
         3.检查是否没有匹配元素(没有匹配元素 为 true)
            boolean b = stream.noneMatch(employee -> employee.getAge() < 0);
         4.返回第一个元素
            Optional<Employee> first = stream.findFirst();
         5.返回任意一个元素
            Optional<Employee> any = stream.findAny();
         6.求流中 元素总个数
            long count = stream.filter(e -> e.getAge() < 400).count();
         7.查找 流中最大值
            Optional<Employee> max = stream.max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
         8.内部迭代(对于流的终止操作)
            stream.forEach(System.out::println);
           集合里(普通方法)
            list.forEach(System.out::println);
      2)规约:
         1.reduce():可以将 流中的元素 反复结合起来,得到一个值,返回。
               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);
            或者
               List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
               Optional<Integer> reduce = list.stream().reduce(Integer::sum);
               System.out.println(reduce);
         3.求 所有员工 工资和:
               List<Employee> employees = EmployeeData.getEmployees();
               Stream<Employee> stream = employees.stream();
               Integer reduce1 = stream.map(e -> e.getAge()).reduce(0, Integer::sum);
               System.out.println(reduce1);
            或者
               List<Employee> employees = EmployeeData.getEmployees();
               Stream<Employee> stream = employees.stream();
               Optional<Integer> reduce1 = stream.map(e -> e.getAge()).reduce((d1, d2) -> d1 + d2);
               System.out.println(reduce1);
      3)收集
         1.collect(Collector c)
            将 流 转换为 其他形式,手机一个 Collector 接口的实现,用于给 Stream 中 元素做汇总的方法。
               Collector 接口中,方法的实现,决定了如何对流,执行收集的操作(如:收集到 List,Set,Map)。
            另外,Collector 类,提供了很多静态方法,可以方便的创建,常见收集器实例。
         2.将 过滤后的流,转换为 List 集合:
            List<Employee> collect = stream.filter(e -> e.getAge() > 100).collect(Collectors.toList());
六:Optional 类(最大化减少空指针异常)
   1.
   2.
   3.
   4.
上一篇:基本数据类型第一篇


下一篇:python 钉钉机器人发送消息