JDK8~13新特性

JDK8新特性–接口–default关键字和静态方法

  • 在jdk1.8以前接口里面是只能有抽象方法,不能有任何方法的实现的

  • jdk1.8里面打破了这个规定,引⼊了新的关键字default,使用default修饰⽅法,可以在接口里面定义具体的⽅法实现

  • 默认方法:接口里面定义⼀个默认⽅法,这个接口的实现类实现了这个接口之后,不用管这个default修饰的方法就可以直接调用,即接口方法的默认实现

  • 静态方法: 接口名.静态方法来访问接口中的静态方法

    public interface Animal {
      void run();
      void eat();
    
      default void breath() {
          System.out.println("使⽤氧⽓呼吸");
      }
    
      static void test() {
          System.out.println("这是静态⽅法");
      }
    }
    

JDK8新特性–新增base64加解密API

  • Jdk1.8的java.util包中,新增了Base64的类

    public static void main(String[] args) {
        Base64.Decoder decoder = Base64.getDecoder();
        Base64.Encoder encoder = Base64.getEncoder();
        String text = "1234567890";
        byte[] textByte = text.getBytes("UTF-8");
        //编码
        String encodedText = encoder.encodeToString(textByte);
        System.out.println(encodedText);
        //解码
        System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
    }
    

JDK8新特性–时间日期处理类

  • 时间处理再熟悉不过,SimpleDateFormat,Calendar等类旧版缺点:java.util.Date是非线程安全的API设计比较差,日期/时间对象⽐较,加减麻烦

  • Java 8通过发布新的Date-Time API (JSR 310)来进⼀步加强对日期与时间的处理

  • 新增了很多常见的api,如⽇期/时间的比较,加减,格式化等

    • 包所在位置 java.time

    • 核心类

      LocalDate:不包含具体时间的日期。
      LocalTime:不含日期的时间。
      LocalDateTime:包含了日期及时间。
      
    • LocalDate 常用API

      LocalDate today = LocalDate.now();
      System.out.println("今天⽇期:" + today);
      //获取年,⽉,⽇,周⼏
      System.out.println("现在是哪年:" + today.getYear());
      System.out.println("现在是哪⽉:" + today.getMonth());
      System.out.println("现在是哪⽉(数字):" + today.getMonthValue());
      System.out.println("现在是⼏号:" + today.getDayOfMonth());
      System.out.println("现在是周⼏:" + today.getDayOfWeek());
      //加减年份, 加后返回的对象才是修改后的,旧的依旧是旧的
      LocalDate changeDate = today.plusYears(1);
      System.out.println("加后是哪年:" + changeDate.getYear());
      System.out.println("旧的是哪年:" + today.getYear());
      //⽇期⽐较
      System.out.println("isAfter: " + changeDate.isAfter(today));
      
      getYear()    int    获取当前日期的年份
      getMonth()    Month    获取当前日期的⽉份对象
      getMonthValue()    int    获取当前日期是第⼏⽉
      getDayOfWeek()    DayOfWeek    表示该对象表示的日期是星期⼏
      getDayOfMonth()    int    表示该对象表示的日期是这个⽉第⼏天
      getDayOfYear()    int    表示该对象表示的日期是今年第⼏天
      withYear(int year)    LocalDate    修改当前对象的年份
      withMonth(int month)    LocalDate    修改当前对象的⽉份
      withDayOfMonth(int dayOfMonth)    LocalDate    修改当前对象在当⽉的日期
      plusYears(long yearsToAdd)    LocalDate    当前对象增加指定的年份数
      plusMonths(long monthsToAdd)    LocalDate    当前对象增加指定的⽉份数
      plusWeeks(long weeksToAdd)    LocalDate    当前对象增加指定的周数
      plusDays(long daysToAdd)    LocalDate    当前对象增加指定的天数
      minusYears(long yearsToSubtract)    LocalDate    当前对象减去指定的年数
      minusMonths(long monthsToSubtract)    LocalDate    当前对象减去注定的⽉数
      minusWeeks(long weeksToSubtract)    LocalDate    当前对象减去指定的周数
      minusDays(long daysToSubtract)    LocalDate    当前对象减去指定的天数
      compareTo(ChronoLocalDate other)    int    ⽐较当前对象和other对象在时间上的⼤⼩,返回值如果为正,则当前对象时间较晚,
      isBefore(ChronoLocalDate other)    boolean    ⽐较当前对象日期是否在other对象日期之前
      isAfter(ChronoLocalDate other)    boolean    ⽐较当前对象日期是否在other对象日期之后
      isEqual(ChronoLocalDate other)    boolean    ⽐较两个日期对象是否相等
      
    • LocalTime 常用API

    • LocalDateTime 常用API

  • 日期时间格式化

    • JDK8之前:SimpleDateFormat来进行格式化,但SimpleDateFormat并不是线程安全的

    • JDK8之后:引⼊线程安全的日期与时间DateTimeFormatter

      LocalDateTime ldt = LocalDateTime.now();
      System.out.println(ldt);
      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm: ss ");
      String ldtStr = dtf.format(ldt);
      System.out.println(ldtStr);
      
    • 获取指定的日期时间对象

      LocalDateTime ldt = LocalDateTime.of(2023, 11, 11, 8, 20, 30);
      System.out.println(ldt);
      
    • 计算日期时间差 java.time.Duration

      LocalDateTime today = LocalDateTime.now();
      System.out.println(today);
      LocalDateTime changeDate = LocalDateTime.of(2020,10,1,10,40,30);
      System.out.println(changeDate);
      Duration duration = Duration.between( today,changeDate);//第⼆个参数减第⼀个参数
      System.out.println(duration.toDays());//两个时间差的天数
      System.out.println(duration.toHours());//两个时间差的⼩时数
      System.out.println(duration.toMinutes());//两个时间差的分钟数
      System.out.println(duration.toMillis());//两个时间差的毫秒数
      System.out.println(duration.toNanos());//两个时间差的纳秒数
      

JDK8新特性–Optional类

  • Optional 类有啥⽤

    • 主要解决的问题是空指针异常(NullPointerException)
    • 怎么解决?
      • 本质是⼀个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空
  • 创建Optional类

    • of()
      • null 值作为参数传递进去,则会抛异常
        Optional<Student> opt = Optional.of(user);
        
    • ofNullable()
      • 如果对象即可能是 null 也可能是非null,应该使用 ofNullable() ⽅法
        Optional<Student> opt = Optional.ofNullable(user);
        
  • 访问 Optional 对象的值

    • get() ⽅法
      Optional<Student> opt = Optional.ofNullable(student);
      Student s = opt.get();
      
    • 如果值存在则isPresent()⽅法会返回true,调用get()方法会返回该对象⼀般使用get之前需要 先验证是否有值,不然还会报错
      public static void main(String[] args) {
      	Student student = null;
      	test(student);
      }
      
      public static void test(Student student) {
          Optional<Student> opt = Optional.ofNullable(student);
          System.out.println(opt.isPresent());
      }
      
  • 兜底 orElse方法

    • orElse()如果有值则返回该值,否则返回传递给它的参数值
      Student student1 = null;
      Student student2 = new Student(2);
      Student result = Optional.ofNullable(student1).orElse(student2);
      System.out.println(result.getAge());
      
      Student student = null;
      int result = Optional.ofNullable(student).map(obj->obj.getAge()).orElse(4);
      System.out.println(result);
      

JDK8新特性–lambda表达式

lambda表达式 使用场景(前提):⼀个接口中只包含⼀个方法,则可以使用Lambda表达式,这样的接口称之为“函数接口” 语法: (params) -> expression
 - 第⼀部分为括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数; 
 - 第⼆部分为⼀个箭头符号:->;
 - 第三部分为方法体,可以是表达式和代码块

参数列表 :
 - 括号中参数列表的数据类型可以省略不写
 - 括号中的参数只有⼀个,那么参数类型和()都可以省略不写

方法体:
 - 如果{}中的代码只有一行,无论有返回值,可以省略{},return,分号,要⼀起省略,其他则需要加上

JDK8新特性–函数式接口

  • Lambda表达式必须先定义接⼝,创建相关方法之后才可使用,这样做十分不便,其实java8已经内置了许多接口,
    例如下面四个功能型接口,所以⼀般很少会由⽤户去定义新的函数式接口
  • Java8的最⼤特性就是函数式接口,所有标注了@FunctionalInterface注解的接口都是函数式接口
    Java8 内置的四⼤核⼼函数式接⼝
    
    Consumer<T> : 消费型接⼝:有⼊参,⽆返回值
    		void accept(T t);
    Supplier<T> : 供给型接⼝:⽆⼊参,有返回值
    		T get();
    Function<T, R> : 函数型接⼝:有⼊参,有返回值
    		R apply(T t);
    Predicate<T> : 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean
    		boolean test(T t);
    

Function

  • 传入⼀个值经过函数的计算返回另⼀个值
  • T:入参类型,R:出参类型
  • 调用方法:R apply(T t)
    // 输出⼊参的10倍
    Function<Integer, Integer> func = p -> p * 100; 
    func.apply(100);
    

BiFunction

  • Function只能接收⼀个参数,如果要传递两个参数,则⽤ BiFunction

    public static void main(String[] args) {
        System.out.println(operator(10, 21, (a, b) -> a + b));
        System.out.println(operator(10, 2, (a, b) -> a - b));
        System.out.println(operator(8, 4, (a, b) -> a * b));
        System.out.println(operator(10, 2, (a, b) -> a / b));
    }
    
    public static Integer operator(Integer a, Integer b, BiFunction<Integer,
            Integer, Integer> bf) {
        return bf.apply(a, b);
    }
    

Consumer

  • Consumer 消费型接口:有入参,无返回值
  • 将 T 作为输入,不返回任何内容
  • 调用方法:void accept(T t);
    public static void main(String[] args) throws Exception {
        Consumer<String> consumer = obj -> {
            System.out.println(obj);
            System.out.println("调⽤短信接⼝发送短信,或者打印⽇志");
        };
    //        sendMsg("8888888", obj -> {
    //            System.out.println(obj);
    //            System.out.println("调⽤短信接⼝发送短信,或者打印⽇志");
    //
    //        });
        sendMsg("8888888", consumer);
    }
    
    public static void sendMsg(String phone, Consumer<String> consumer) {
        consumer.accept(phone);
    }
    

Supplier

  • Supplier: 供给型接口:无入参,有返回值
  • T:出参类型;没有入参
  • 调用方法:T get();
    public static void main(String[] args) {
        //Student student = new Student();
        Student student = newStudent();
        System.out.println(student.getName());
    }
    
    public static Student newStudent() {
        Supplier<Student> supplier = () -> {
            Student student = new Student();
            student.setName("默认名称");
            return student;
        };
        return supplier.get();
    }
    
    class Student{
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    

Predicate

  • Predicate: 断⾔型接口:有⼊参,有返回值,返回值类型确定是boolean
  • T:入参类型;出参类型是Boolean
  • 调用方法:boolean test(T t);
    public static void main(String[] args) {
        List<String> list =
                Arrays.asList("awewrwe", "vdssdsd", "aoooo", "psdddsd");
        List<String> results = filter(list, obj -> obj.startsWith("a"));
        System.out.println(results);
    }
    
    public static List<String> filter(List<String> list,
                                      Predicate<String> predicate) {
        List<String> results = new ArrayList<>();
        for (String str : list) {
            if (predicate.test(str)) {
                results.add(str);
            }
        }
        return results;
    }
    

JDK8新特性–方法与构造函数引用

  • 以前方法调用对象.方法名或者类名.方法名
  • jdk1.8提供了另外⼀种调用方式 ::
    说明:⽅法引⽤是⼀种更简洁易懂的lambda表达式,操作符是双冒号::,⽤来直接访问类或者实例
    已经存在的⽅法或构造⽅法
    
    通过⽅法引⽤,可以将⽅法的引⽤赋值给⼀个变量
    
    语法:左边是容器(可以是类名,实例名),中间是" :: ",右边是相应的⽅法名
    
    静态⽅法,则是ClassName::methodName。如 Object ::equals
    实例⽅法,则是Instance::methodName
    构造函数,则是 类名::new;
    
    单个参数
    Function<⼊参1, 返回类型> func = ⽅法引⽤
    应⽤ func.apply(⼊参);
    
    2个参数
    BiFunction<⼊参1,⼊参2, 返回类型> func = ⽅法引⽤
    应⽤ func.apply(⼊参1,⼊参2);
    
    public static void main(String[] args) {
        // 使⽤双冒号::来构造静态函数引⽤
        Function<String, Integer> fun = Integer::parseInt;
        Integer value = fun.apply("1024");
        System.out.println(value);
        // 使⽤双冒号::来构造⾮静态函数引⽤
        String content = "abcedfg";
        Function<Integer, String> func = content::substring;
        String result = func.apply(1);
        System.out.println(result);
        // 构造函数引⽤,多个参数
        BiFunction<String, Integer, User> biFunction = User::new;
        User user1 = biFunction.apply("小王", 28);
        System.out.println(user1.toString());
        //构造函数引⽤,单个参数
        Function<String, User> function = User::new;
        User user2 = function.apply("小王");
        System.out.println(user2.toString());
        // 函数引⽤也是⼀种函数式接⼝,可以将函数引⽤作为⽅法的参数
        sayHello(String::toUpperCase, "www.baidu.com");
    }
    
    /**
     * @param func  函数引⽤
     * @param param 对应的参数
     */
    private static void sayHello(Function<String, String> func, String
            param) {
        String result = func.apply(param);
        System.out.println(result);
    }
    
    class User {
        private String username;
        private Integer age;
    
        public User() {}
    
        public User(String username) {
            this.username = username;
        }
    
        public User(String username, Integer age) {
            this.username = username;
            this.age = age;
        }
    }
    

JDK8新特性–Stream

  • 什么是stream
    • Stream 中文称为 “流”,通过将集合转换为这么⼀种叫做 “流”的元素队列,通过声明性方式,能够对集合中的每个元素进行⼀系列并行或串行的流水线操作
    • 元素是特定类型的对象,所以元素集合看作⼀种流, 流在管道中传输, 且可以在管道的节点上进行处理, 比如 排序,聚合,过滤等操作在这里插入图片描述
  • 操作详情
    • 数据元素便是原始集合,如List、Set、Map等
    • 生成流,可以是串行流stream() 或者并行流 parallelStream()
    • 中间操作,可以是 排序,聚合,过滤,转换等
    • 终端操作,很多流操作本身就会返回⼀个流,所以多个操作可以直接连接起来,最后统⼀进行收集

map

  • 将流中的每⼀个元素 T 映射为 R(类似类型转换)

    // 案例一
    List<String> list = Arrays.asList("springboot教程", "微服务教程", "并发编程", " 压⼒测试", " 架构课程");
    List<String> resultList = list.stream().map(obj -> "0到100自学:" + obj).collect(Collectors.toList());
    System.out.println(resultList);
    
    // 案例二
    List<User> list = Arrays.asList(new User(1, "⼩东", "123"), 
            new User(21, "jack", "rawer"), 
            new User(155, "tom", "sadfsdfsdfsd"), 
            new User(231, "marry", "234324"), 
            new User(100, "⼩D", "122223"));
    List<UserDTO> userDTOList = list.stream().map(obj -> {
        UserDTO userDTO = new UserDTO(obj.getId(), obj.getName());
        return userDTO;
    }).collect(Collectors.toList());
    System.out.println(userDTOList);
    

filter

  • 用于通过设置的条件过滤出元素,筛选过滤出符合条件的元素 需求:过滤出字符串长度大于5的字符串

    List<String> list = Arrays.asList("springboot", "springcloud",
            "redis", "git", "netty", "java", "html", "docker");
    List<String> resultList = list.stream().filter(obj -> obj.length() >
            5).collect(Collectors.toList());
    System.out.println(resultList);
    

sorted

  • sorted() 对流进行自然排序, 其中的元素必须实现Comparable接口
    List<String> list = Arrays.asList("springboot", "springcloud", "redis", "git", "netty", "java", "html", "docker");
    List<String> resultList = list.stream().sorted().collect(Collectors.toList());
    
  • sorted(Comparator<? super T> comparator) 用来自定义升降序
    List<String> list = Arrays.asList("springboot", "springcloud", "redis", "git", "netty", "java", "html", "docker");
    //根据⻓度进⾏排序
    //方式一
    List<String> resultList = list.stream().sorted(Comparator.comparing(obj -> obj.length())).collect(Collectors.toList());
    //方式二
    List<String> resultList = list.stream().sorted(Comparator.comparing(obj -> obj.length(), Comparator.reverseOrder())).collect(Collectors.toList());
    //方式三
    List<String> resultList = list.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
    System.out.println(resultList);
    

limit

  • 截断流使其最多只包含指定数量的元素
    List<String> list = Arrays.asList("springboot", "springcloud", "redis", "git", "netty", "java", "html", "docker");
    //limit截取
    List<String> resultList = list.stream().sorted(Comparator.comparing(String::length).reversed())
            .limit(3).collect(Collectors.toList());
    System.out.println(resultList);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值