zoukankan      html  css  js  c++  java
  • JDK1.8的新特性

    前言

    以前大致了解过jdl1.8的一些新特性,长时间不用,慢慢忘记了,最近又捡起来看了下,并参考了一些博客,有些许新的收获,特此记录下。

    参考博客: https://blog.csdn.net/chengwangbaiko/article/details/73433645

    正文

    关于1.8的一些新特性,会仔细研究过之后慢慢进行更新。

     1. 接口的扩展方法

    在jdk1.8之前,接口中只允许有抽象方法,但是在1.8之后,接口中允许有一个非抽象的方法,但是必须使用default进行修饰,叫做扩展方法。

    public interface UserService{
      
        void deleteUser(User user);
        
        default UsershowUser(User user){
        System.out.println("show User");
         user=Optional.ofNullable(user).orElse(new User());
         user.setName("这是经过扩展方法之后的user");
         return user;
        }
    
    }

    在我们实现接口之后,可以选择对方法直接使用或者重写。

    2. 函数式接口,方法与构造方法的引用

    函数式接口:接口中只有一个方法,可以对应一个lambda表达式。通过匿名内部类或者方法传递进行连接,调用接口即调用对应的方法。

    @FunctionalInterface
    public interface Converter<F,T> {
        T converter(F f);
    }
    //方法传递,使用的是Integer.valueOf()的方法
    Converter<String ,Integer> converter = Integer::valueOf;

    3. 其余的一些接口:

    3.1:Predicate<T>接口:

      接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非):

    复制代码
    public static void main(String[] args) {
            //定义函数式接口,需要注意的是:Predicate接口指向方法的时候,指向的必须是返回值为boolean类型的方法。
            Predicate<String> predicate = s -> s.length() < 1; //定义函数式接口
            Predicate<String> predicate2 = Objects::nonNull;
            //Predicate接口的and方法,表示与。negative()表示的是否,or()表示的是或
            System.out.println(predicate2.test("ssss"));                //true
            System.out.println(predicate.and(predicate2).test("sss"));  //false
            System.out.println(predicate.or(predicate2).test("sss"));   //true
        }
    复制代码

    3.2 Optional<T>类

      Optional<T>类,继承Object,私有构造,是一个可能包含或不包含非空值的容器对象,如果一个值存在, isPresent()将返回true和get()将返回值。

      想要获取对象可以直接使用一下几种方法:

    Optional<T>的静态方法:
    1. Optional.empty()-->返回一个空的Optional实例
    2. Optional.of(T value) --> 返回一个具有Optional的当前非空值的optional实例,需要注意的是:这里传的应该是非空值。如果可能为空,请用下面的
    3. Optional.ofNullable(T value) -->返回一个具有Optional的当前值的optional实例,如果值为空,则返回一个空的Optional实例。

      关于Optional<T>的api,参考jdk1.8的API文档。

      Optional<T>的一些应用实例:

    1. 结合stream进行使用:后面详细说
    2. 单独使用:Optional.ofNullable(user.getUserName()).orElse("hello,name is null").toString(); 
    //解释下:如果你数据库查询出的user的name字段未知,你要进行null判断,如果未null,则显示为“hello,name is null” 进行返回。toString是为了查询到的name不是String的时候进行转换。

    3.2 Function接口、Supplier 接口、Consumer 接口等

      这些接口均是和lambda表达式进行配合,其中Function可以进行多个lambda的组合。

      (具体的详情可以参见:jdk1.8的api文档)

    4. lamdba表达式的用法

    4.1创建匿名内部类

      在1.8之前,我们创建匿名内部类的时候,是这样的:

    复制代码
     Converter<String ,Integer> converter = new Converter<String, Integer>() {
            @Override
            public Integer converter(String s) {
                return Integer.parseInt(s);
            }
        };
    复制代码

      在1.8之后呢,我们可以这样来创建

    Converter<String ,Integer> converter = (f) -> {
            return Integer.valueOf(f);
        };

      更简单的:如果你的方法体只有一句的话,你可以这样来创建

    Converter<String ,Integer> converter = (f) -> Integer.parseInt(f);

     4.2 lambda表达式和Stream接口对集合的操作《重点》

      1. Stream类似于流,单向,不可往复。可以对集合的所有元素进行筛选,过滤,修改等,但是只能对数据遍历一次,如果需要第二次操作,必须继续创建Stream流。

      2. Stream操作分为三个步骤:创建Stream--》中间操作--》最终操作。

    4.2.1 构建流的几种方法
     Stream<String> stream1 = Stream.of("aa", "bb", "cc"); //直接使用静态方法,获取指定值的顺序排序流
     String [] strArray = {"a", "b", "c"};
     Stream<String> stream2 = Arrays.stream(strArray); //使用的Arrays类的stream方法
     List<String> list = Arrays.asList(strArray);
     Stream<String> stream3 = list.stream();//直接使用集合获取流
    4.2.2 常用的方法
    1. foreach方法
    复制代码
    public static void main(String[] args) {
    
            String[] arrs = {"hello","world","welcome","meet","you","aaa"};
            List<String> list = Arrays.asList(arrs);
            test1(list);
        }
    
        public static void test1(List list){
            list.stream().forEach(x -> System.out.println(x)); //拿到每个元素打印
            list.stream().forEach(System.out::println);  //如果只进行打印,可以使用方法的引用。
        }
    复制代码
    2. 对数据进行过滤
     list.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);  //aaa,过滤开始元素为a的字符串。
    3. 对数据进行排序
    复制代码
    list.stream().filter((user) -> user.getName().startsWith("a")).sorted().forEach(System.out::println); 

     //需要特别注意的是:你对user进行排序,那么user类必须实现了Comparable<User>接口,并重写compareTo方法,来定义比较方法才可以,否则会报无法转换为Compare错误!

    public class User implements Comparable<User>,Serializable {
      private Integer age;
      getter,setter省略。。。
      @Override
      public int compareTo(User user) {
       return user.getAge() - this.getAge() ;
      }
    }
    实现了Comparable接口之后,系统会知道如何进行排序比较。
    复制代码

    需要注意的是:这里排序之后只是流中进行了排序,如果想要得到排序之后的集合,需要对流进行toArray操作,然后重新转换成集合。

    4. map操作

    返回由给定函数应用于此流的元素的结果组成的流。 也就是我定义一个方法,对流中的每个元素进行操作。如果需要返回修改之后的list,则还需要toArray

    复制代码
    list.stream().map((user -> {
                user.setName(user.getName().toUpperCase());
                return user;
            })).forEach(System.out::println);  //定义了一个Function<User,User>接口的匿名内部类,使用lambda表达式来实现。

     //写的更加明显一点如下:

    Function<User,User> function = (user -> {
    user.setName(user.getName().toUpperCase());
    return user;
    }); //Function接口的匿名内部类
    list.stream().map(function).forEach(System.out::println);
    复制代码
    5. count()操作:最终操作
    long count = list.stream().filter((user) -> user.getName().startsWith("a")).count();
    System.out.println("所有以a开头用户名字个数为: " + count);  // 所有以a开头用户名字个数为: 5

    当使用最终操作之后,流就已经不存在了。

    6. reduce操作
     Stream<String> stream1 = Stream.of("aa", "bb", "cc"); //直接使用静态方法,获取指定值的顺序排序流
     stream1.reduce((s1,s2) ->s1 +"#" +s2).ifPresent(System.out::println);  //aa#bb#cc

    操作的目的是:允许通过指定的函数来讲stream中的多个元素规约为一个元素,最后得到的是一个Optional接口容器表示,如果想拿到值,需要get()来拿到。

    7. 关于Stream的串行和并行
    list.stream()-->即进行串行操作,单线程。时间长
    list.parallelStream()-->并行操作,多线程同时进行。需要时间短

    5. 时间表达式

    复制代码
    LocalDate today = LocalDate.now(); //现在的日期
    LocalDate tomorrow = today.plusDays(1); //今天之后的一天的日期
    LocalTime time = LocalTime.of(10,10,10,358); //设定时间
    LocalTime now = LocalTime.now(); //时间
    LocalDateTime atDate = now.atDate(today);  //日期+时间
    LocalDateTime dateTime = LocalDateTime.now(); //当前日期和时间
    复制代码

    详情见JDK1.8Api。

     
  • 相关阅读:
    06 | x86架构:有了开放的架构,才能打造开放的营商环境
    02 | 学习路径:爬过这六个陡坡,你就能对Linux了如指掌
    01 | 入学测验:你究竟对Linux操作系统了解多少?
    String、StringBuffer与StringBuilder区别
    JavaSE语言基础之字符串
    JavaSE语言基础之数组及其排序
    JavaSE语言基础之流程控制语句
    JavaSE语言基础之数据类型
    Java开发环境配置
    shell 脚本 自增
  • 原文地址:https://www.cnblogs.com/Smina/p/11986937.html
Copyright © 2011-2022 走看看