美文网首页
Java8初探

Java8初探

作者: 伤口不该结疤 | 来源:发表于2020-12-16 16:25 被阅读0次

    1、概述

    1.1 为什么要学习java8

    java8可以让我们编写更为简洁的代码

    1.1.1 【示例1】lambda表达式

    • 普通写法

      普通写法
    • java8 lambda表达式写法

    java8 lambda表达式写法

    1.1.2 【示例2】stream的使用

    • 普通写法
    普通写法
    • java8写法
    img_17.png

    1.1.3 【示例3】filter使用

    • 普通写法
    普通写法
    • 行为参数化,把代码传统给方法
    行为参数化,把代码传统给方法

    1.2 java8支持的一些新特性

    • Lambdas表达式
    • 方法引用
    • 默认方法
    • Stream API
    • Date Time API

    1.3 函数式编程

    函数式编程是一种编程范式,所谓编程范式是指一种编程风格

    1.3.1 常见的编程范式

    • 指令式编程

      是一种描述电脑所需作出的行为的编程典范

    汇编指令
    • 结构化编程

      采用子程序、块结构、for循环以及while循环等结构进行编程

    • 过程式编程

      派生自结构化编程,主要采取程序调用(procedure call)或函数调用(function call)的方式来进行流程控制

    • 面向对象编程

      一切皆对象

    • 函数式编程

      在函数式编程中,函数是第一类对象,意思是说一个函数,既可以作为其它函数的参数(输入值),也可以从函数中返回(输入值),被修改或者被分配给一个变量

    1.3.2 java8中的函数式编程

    在函数式编程出现之前,编程的整个目的在于操作值,值是一等公民。

    筛选隐藏文件

    而函数式编程将方法也提升为一等公民,让编程更简单。将方法引用File::isHidden作为参数传递给listFiles

    将方法引用File::isHidden作为参数传递给listFiles 两种方式对比

    一言以蔽之,函数式编程只是一种编程思想,核心是函数是一等公民,而Java8是利用lambda表达式、方法引用等新特性,将函数式编程的思想引入到了Java中

    1.4 为什么要变化

    害怕被其他语言替代

    1.4.1 java版本历史

    从java版本历史来看,java更新缓慢

    java版本历史

    1.4.2 运行在jvm上的语言

    java只是运行在jvm上的其中一种语言。同样运行在jvm上的还有scala、kotlin等,如果java不持续更新,就有可能被其他语言给替代掉

    运行在jvm上的语言

    1.4.3 Martin Odersky(马丁·奥德斯基)

    Martin Odersky马丁·奥德斯基是函数式编程的爱好者,他终生一直在JVM平台上工作。他发明的第一个语言叫Pizza(1996年),为JVM引入了泛型,并证明了可以在 JVM 平台上实现函数式语言特性。
    而Scala(2003年)是由他发明第二种编程语言 ,设计初衷是要集成面向对象编程和函数式编程的各种特性,Scala运行于Java虚拟,并兼容现有的Java程序
    可以说是Pizza带来了Java1.5,Scala带来了Java8

    1.4.4 强大的竞争对手kotlin

    kotlin

    java上定义一个类


    java上定义一个类

    kotlin上定义一个类


    kotlin上定义一个类

    kotlin推动着java发展,JDK15(2020年9月)推出了Records新特性,也可以达到简写类的目的


    Point类

    record Point(int x, int y) { }

    2. lambda表达式

    2.1 什么是lambda表达式

    2.1.1 定义

    • Lambda表达式是一个匿名函数,即没有函数名的函数
    • 可以把函数作为参数传递给方法
    • 让代码更简洁
    • lambda表达式由参数、箭头和主体组成


      lambda表达式
      由参数、箭头和主体组成

    2.1.2 语法格式

    • 格式

      (parameters) -> expression

      (parameters) -> {statements;}

    • 以下哪些不是lambda表达式

      (1) () -> {}
      (2) () -> "Raoul"
      (3) () -> {return "Mario";}
      (4) (Integer i) -> return "Alan" + i;
      (5) (String s) -> {"IronMan";}
      

    2.2 在哪里可以使用以及如何lambda

    在函数式接口上可以使用lambda表达式

    2.2.1 什么是函数式接口

    • 只有一个抽象方法的接口叫做函数式接口
    • 函数式接口会使用@FunctionalInterface标注,在编译时会进行检查,如果不是函数式接口就会报错

    2.2.3 以下哪些是函数式接口?

         public interface Adder{
              int add(int a, int b);
         }
     
         public interface SmartAdder extends Adder{
              int add(double a, double b);
         }
     
         public interface Nothing{
         }
    

    2.2.3 【案例1】为什么Runnbale可以简写

    为什么Runnbale可以简写
    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("hello lambda");
        }
    };
    
    • Runnable接口只有一个抽象方法,因此它是一个函数式接口


      Runnable接口只有一个抽象方法
    • 可以按照lambda的语法格式,进行简化

      1. 调用Runnable的run方法,传入的参数为空,即:()

      2. run方法里面的部分,是一个语句,直接copy出来可行了,即:System.out.println("hello lambda")

      3. 将()和System.out.println("hello lambda");使用->组合起来,得到:() -> System.out.println("hello lambda");

      4. 最后,将lambda表达式作为参数,传给Thread

         new Thread(() -> System.out.println("hello lambda"))
        
      5. 如果是多行的情况,就使用{}

           new Thread(() -> {
               System.out.println("hello lambda");
               System.out.println("multi-line");
           });
        
    • IDEA自动转换功能


      IDEA自动转换功能
      自动转换

    2.2.4 【案例2】Comparator

    • 按照名字进行排序
      List<Person> list = new ArrayList<>();
      list.add(new Person(18, "Tom"));
      list.add(new Person(6, "Jack"));
      list.add(new Person(20, "Hello"));
      list.add(new Person(17, "Apple"));
    
    • 编写compare
      // 按照名字进行排序
      list.sort(new Comparator<Person>() {
          @Override
          public int compare(Person o1, Person o2) {
              return o1.getName().compareTo(o2.getName());
          }
      });
    
    • 改成lambda

      • 传入的参数为o1, 02,写作(o1, o2)

      • 语句为o1.getName().compareTo(o2.getName())

      • 组合到一起: (o1, o2) -> o1.getName().compareTo(o2.getName())

      • 做为参数传给list.sort,得到:list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));

      • 输出结果

            Person{age=17, name='Apple'}
            Person{age=20, name='Hello'}
            Person{age=6, name='Jack'}
            Person{age=18, name='Tom'}
        
    • 为什么Comparator是函数式接口


      为什么Comparator是函数式接口
    为什么Comparator是函数式接口

    2.3 方法引用

    2.3.1 什么是方法引用

    • 一种lambda的简化写法

      (o1, o2) -> o1.getName().compareTo(o2.getName())
      
      可以简化为:
      
      Comparator.comparing(Person::getName)
      
    • 格式

      要调用的类::要调用类的方法

    • 使用规则
    类型 示例
    类名::静态方法 Person::sayHello
    类名::实例方法 Person::getName
    对象::实例方法 comparator::compare
    类名::new Person::new
    • 示例

        // 类名::静态方法
        list.stream().forEach(Person::sayHello);
      
        // 类名::实例方法
        list.stream().forEach(Person::getName);
      
        // 对象::实例方法
        NameComparator comparator = new NameComparator();
        list.stream().sorted(comparator::compare).forEach(System.out::println);
      
        // 类名::new
        List<String> nameList =  Arrays.asList("Jay", "Tommy", "Helen");
        nameList.stream()
                .map(Person::new)
                .forEach(System.out::println);
      

    3. Stream API

    3.1 什么是流

    3.1.1 基本概念

    Stream是Java8的新API,它允许以声明性的方式处理数据集合

    3.1.2 什么是声明性方式

    通过查询语句来表示,而不是临时编写一个实现。例如:查询年龄小于18岁的人的姓名

    • 声明性方式查询

      SELECT name FROM persons WHERE age < 18

    • 临时编写语句

      for (Person person : list) {
        if (person.getAge() < 18) {
            System.out.println(person.getName());
        }
      }
      
    • Stream的写法

      list.stream()
        .filter(person -> person.getAge() < 18)
        .map(Person::getName)
        .forEach(System.out::println);
      
    Stream

    3.2 怎么用

    3.2.1 使用流的三个步骤

    • 生成流:将list、数组等要操作的数据,转换成流
    • 中间操作:filter、map等
    • 终端操作:生成一个结果
    使用流的三个步骤

    3.2.2 生成流

    • 由数组/List创建

        int[] arrays = new int[]{4, 5, 8, 10, 0, -1, 99, -20};
        // 将数组转换成流
        Arrays.stream(arrays);
        
        List list = Arrays.asList(arrays);
        // 将List转换成流
        list.stream();
      
    • 由值生成

      Stream<String> stream =  Stream.of("a", "bb", "cc");
      
    • 文件生成

        String path = "E:\\Code\\Java8\\src\\com\\test02\\Person.java";
        try (Stream<String> lines = Files.lines(Paths.get(path))) {
            lines.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
      
    • 由函数生成

      Stream.iterate(0, n -> n + 1).forEach(System.out::println);
      

      输出:

        0
        1
        2
        ... ...
        202687
        202688
        202689
        202690
        202691
        202692
      

      限制值输出前10个

        Stream.iterate(0, n -> n + 1)
                  .limit(10)
                  .forEach(System.out::println);
      

    3.2.3 终端操作

    • forEach

      int[] arrays = new int[]{4, 5, 8, 10, 0, -1, 99, -20};
      // 终端操作forEach
      Arrays.stream(arrays).forEach(System.out::println);
      
    • count

        // 终端操作count
        long count = Arrays.stream(arrays).count();
        System.out.println(count);
      
    • collect

        List<Integer> list = Stream.iterate(0, n -> n + 1)
                .limit(5)
                .collect(toList());
      

    3.2.3 中间操作

    1. 筛选

    • filter & distinct
        List<Integer> numbers = Arrays.asList(1, 6, 7, 1, 1, 2, 3, 2, 6);
        numbers.stream()
                .filter(i -> i % 2 == 0)
                .distinct()
                .forEach(System.out::println);
    

    输出

      6
      2
    
    • limit & skip
        Stream.iterate(0, n -> n + 1)
        .limit(6)
        .skip(2)
        .forEach(System.out::println);
    

    输出

        2
        3
        4
        5
    

    2. 映射

    • map
      对流中的每一个元素应用函数

        List<Person> list = new ArrayList<>();
        list.add(new Person(18, "Tom"));
        list.add(new Person(6, "Jack"));
        list.add(new Person(20, "Hello"));
        list.add(new Person(17, "Apple"));
      
        list.stream()
                .filter(person -> person.getAge() < 18)
                .map(Person::getName)
                .forEach(System.out::println);
      

      输出

        Jack
        Apple
      
    • flatMap

      flatMap

    输出:

      h
      e
      l
      l
      o
      j
      a
      v
      a
      8
    

    参考

    相关文章

      网友评论

          本文标题:Java8初探

          本文链接:https://www.haomeiwen.com/subject/hpxogktx.html