JDK1.8新特性学习笔记

本文深入探讨Java 8引入的重要特性,包括Lambda表达式、Stream API、Optional类、接口中的默认方法与静态方法、新的时间日期API以及重复注解与类型注解,旨在帮助开发者掌握最新Java编程技巧。
摘要由CSDN通过智能技术生成

简介

在这里插入图片描述
在这里插入图片描述

一、Lambda表达式

在这里插入图片描述

语法格式

在这里插入图片描述
Lambda表达式只能用于函数式接口,即接口里只有一个方法,函数式接口上可加上@FunctionalInterface注解。
Lambda表达式的参数列表的数据类型可以省略不写,JVM编译器可以通过上下文推断出数据类型,即“类型推断”。

  1. 无参数,无返回值

    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello Java!");
        }
    };
    r1.run();
    

    写为Lambda表达式:

    Runnable r2 = () -> System.out.println("Hello Lambda!");
    r2.run();
    
  2. 有一个参数,无返回值(只有一个参数时,小括号可以不写)

    Consumer<String> con1 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    con1.accept("hello");
    

    写为Lambda表达式:

    Consumer<String> con2 = (s) -> System.out.println(s);
    //只有一个参数时,小括号可以不写
    //Consumer<String> con2 = s -> System.out.println(s);
    con2.accept("lambda");
    
  3. 有两个以上的参数,有返回值,Lambda体中有多条语句

    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            System.out.println("hello");
            return Integer.compare(o1, o2);
        }
    };
    System.out.println(com1.compare(2, 3));	
    

    写为Lambda表达式:

    Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println("lambda");
            return Integer.compare(o1, o2);
        };
    System.out.println(com1.compare(2, 3));	
    
  4. 有两个参数,有返回值(如果只有返回语句,可省略{}和return)

    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return Integer.compare(o1, o2);
        }
    };
    System.out.println(com1.compare(2, 3));	
    

    写为Lambda表达式:

    Comparator<Integer> com2 = (x, y) -> Integer.compare(x, y);
    System.out.println(com2.compare(2, 3));
    

在这里插入图片描述

函数式接口

在这里插入图片描述
在这里插入图片描述

    public static void main(String[] args) {
        //Consumer<T> 消费型接口:有参数,无返回值
        happy(1000, (m) -> System.out.println("消费" + m + "元"));

        //Supplier<T> 供给型接口:有返回值
        List<Integer> lists = getNumList(10, () -> (int)(Math.random() * 100));
        lists.forEach(System.out::println);

        //Function<T, R> 函数型接口:对传参进行处理后返回结果
        String s = strHandler("\t\t\t aaa  ", (str) -> str.trim());
        System.out.println(s);
        System.out.println(strHandler("ABCD", (str) -> str.toLowerCase()));

        //Predicate<T> 断言型接口:对传参进行判断/过滤
        List<String> list = Arrays.asList("hello lambda aa bbb cccccc www ok".split(" "));
        List<String> strings = filterStr(list, (s) -> s.length() > 3);
        strings.forEach(System.out::println);
    }

    public static void happy(double money, Consumer<Double> con){
        con.accept(money);
    }

    public static List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> lists = new ArrayList<>();

        for (int i = 0; i < num; i++) {
            lists.add(sup.get());
        }
        return lists;
    }

    public static String strHandler(String str, Function<String, String> fun){
        return fun.apply(str);
    }

    public static List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();

        for (String s : list) {
            if(pre.test(s)){
                strList.add(s);
            }
        }
        return strList;
    }

在这里插入图片描述

方法引用

在这里插入图片描述

    //对象::实例方法名
    Consumer<String> con = (x) -> System.out.println(x);
    Consumer<String> con2 = System.out::println;

    //类::静态方法名
    Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
    Comparator<Integer> com2 = Integer::compare;

    //类::实例方法名
    BiPredicate<String, String> bp = (x, y) -> x.equals(y);
    BiPredicate<String, String> bp2 = String::equals;

构造器引用

在这里插入图片描述

    //无参构造器
    Supplier<Employee> emp = () -> new Employee();
    Supplier<Employee> emp2 = Employee::new;

    //一个参数的构造器
    Function<Integer, Employee> emp3 = (x) -> new Employee(x);
    Function<Integer, Employee> emp4 = Employee::new;

数组引用

在这里插入图片描述

     Function<Integer, String[]> fun = (x) -> new String[x];
     String[] strs = fun.apply(5);
     System.out.println(strs.length);

     Function<Integer, String[]> fun2 = String[]::new;
     String[] strs2 = fun2.apply(4);
     System.out.println(strs2.length);

二、Stream API

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

创建流

   //创建流
   
   //1. Conllection系列的集合可以通过stream()或parallelStream()获取流
   //stream()为串行
   //parallelStream()为并行
   List<String> list = new ArrayList<>();
   Stream<String> stream1 = list.stream();

   //2. 数组通过Arrays的静态方法stream()获取流
   Employee[] emps = new Employee[10];
   Stream<Employee> stream2 = Arrays.stream(emps);

   //3. 通过Stream的静态方法of()获取流
   Stream<String> stream3 = Stream.of("aa", "bb", "ccc");

   //4. 创建无限流
   //4.1. 迭代
   Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
   stream4
       //中间操作
       .limit(10)
       //终止操作
       .forEach(System.out::println);
   
   //4.2. 生成
   Stream.generate(() -> Math.random())
       //中间操作
       .limit(5)
       //终止操作
       .forEach(System.out::println);

中间操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

筛选与切片

在这里插入图片描述

	List<Employee> employees = Arrays.asList(
         new Employee("张三", 18, 9999.99),
         new Employee("李四", 58, 5555.55),
         new Employee("王五", 26, 3333.33),
         new Employee("赵六", 36, 6666.66),
         new Employee("田七", 12, 8888.88),
         new Employee("田七", 12, 8888.88),
         new Employee("田七", 12, 8888.88)
    );


   //中间操作:不会执行任何操作
   //filter
   Stream<Employee> stream1 = employees.stream()
                               //过滤
                               .filter((e) -> {
                                   //没有终止操作时,中间操作不会执行(惰性求值/延迟加载)
                                   System.out.println("中间操作:过滤");
                                   return e.getAge() > 35;
                               });
   //终止操作:一次性执行全部内容,即"惰性求值"
   stream1.forEach(System.out::println);

   //limit
   employees.stream()
           //过滤,money大于5000
           .filter(e -> {
               System.out.println("---money > 5000---");
               return e.getMoney() > 5000;
           })
           //截断,截取2个(截取指定数量后,剩下的不会进行,提高效率)
           .limit(2)
           //终止操作
           .forEach(System.out::println);

   //skip
   employees.stream()
           .filter(e -> e.getMoney() > 5000)
           //跳过,跳过前2个元素
           .skip(2)
           .forEach(System.out::println);

   //distinct
   employees.stream()
       .filter(e -> e.getMoney() > 5000)
       .skip(2)
       //去重,去除重复元素(按照hashCode()和equals()去除重复元素,所以需要重写hashCode()和equals())
       .distinct()
       .forEach(System.out::println);

映射

在这里插入图片描述

    //map
    List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");

    list.stream()
        .map((str -> str.toUpperCase()))
        .forEach(System.out::println);

    System.out.println("------------------------------");

    employees.stream()
            .map(emp -> emp.getName())
            .forEach(System.out::println);
public static void main(String[] args) {
    //flatMap
    Stream<Stream<Character>> stream = list.stream()
            //list的每个元素都放入filterCharacter方法拆成char数组放到一个新的list的流中
            .map(TestStream2::filterCharacter);
    //遍历流,Stream<Stream<Character>> {[a,a,a],[b,b,b],[c,c,c],[d,d,d]}
    stream.forEach((sm) -> {
        //遍历流中的流,即Stream<Character> [a,a,a]
        sm.forEach(System.out::println);
    });

    System.out.println("------------------------------");

    Stream<Character> stream2 = list.stream()
            //整合成一个流     {a,a,a,b,b,b,c,c,c,d,d,d}
            .flatMap(TestStream2::filterCharacter);
    stream2.forEach(System.out::println);
}

public static Stream<Character> filterCharacter(String str){
    List<Character> list = new ArrayList<>();

    for (char ch : str.toCharArray()) {
        list.add(ch);
    }
    return list.stream();
}

排序

在这里插入图片描述

    //sorted():按照默认规则进行排序
    List<String> list = Arrays.asList("bbb", "ddd", "aaa", "ccc");

    list.stream()
            .sorted()
            .forEach(System.out::println);

	System.out.println("------------------------------");

    employees.stream()
            //自定义排序规则
            .sorted((e1, e2) -> {
                //年龄相同按姓名排
                if (e1.getAge().equals(e2.getAge())) {
                    return e1.getName().compareTo(e2.getName());
                }else{
                    //按照年龄排序
                    return e1.getAge().compareTo(e2.getAge());
                }
            })
            .forEach(System.out::println);

终止操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查找与匹配

在这里插入图片描述

   	List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 58, 5555.55, Employee.Status.BUSY),
            new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),
            new Employee("赵六", 36, 6666.66, Employee.Status.FREE),
            new Employee("田七", 12, 8888.88, Employee.Status.BUSY)
    );

    //终止操作

    //allMatch
    boolean b1 = employees.stream()
            //检查所有元素是否符合条件,都符合才为true
            .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
    System.out.println(b1);

    //anyMatch
    boolean b2 = employees.stream()
            //检查所有元素是否有符合条件的元素,有一个符合就为true
            .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
    System.out.println(b2);

    //noneMatch
    boolean b3 = employees.stream()
            //检查所有元素是否都不符合条件,都不符合为true
            .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
    System.out.println(b3);

    //findFirst
    Optional<Employee> first = employees.stream()
            //按照工资排序
            .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
            //获取第一个元素
            .findFirst();
    System.out.println(first.get());

    //findAny
    Optional<Employee> any = employees.parallelStream()
            //过滤出所有空闲状态的员工
            .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
            //随机获取一个员工
            .findAny();
    System.out.println(any);

    //count
    long count = employees.stream()
            //查看总数
            .count();
    System.out.println(count);

    //max
    Optional<Employee> max = employees.stream()
            //按照工资获取最大值
            .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
    System.out.println(max.get());

    //min
    Optional<Double> min = employees.stream()
            //提取所有的工资数据
            .map(Employee::getSalary)
            //获取最小值
            .min(Double::compare);
    System.out.println(min.get());

归约与收集

在这里插入图片描述

    //reduce
    List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    Integer sum = list.stream()
            //合并,起始索引为0,执行操作相加
            .reduce(0, (x, y) -> x + y);
    System.out.println(sum);


    Optional<Double> sum2 = employees.stream()
            //提取所有的工资数据
            .map(Employee::getSalary)
            //合并,工资总和
            .reduce(Double::sum);
    System.out.println(sum2.get());

在这里插入图片描述

    //collect
    List<String> list = employees.stream()
                            //获取所有名字数据
                            .map(Employee::getName)
                            //收集数据,并存放到list中
                            .collect(Collectors.toList());
    list.forEach(System.out::println);

    System.out.println("-----------------------------");

    Set<String> set = employees.stream()
            //获取所有名字数据
            .map(Employee::getName)
            //收集数据,并存放到set中,有去重功能
            .collect(Collectors.toSet());
    set.forEach(System.out::println);

    System.out.println("-----------------------------");


    Set<String> hs = employees.stream()
            //获取所有名字数据
            .map(Employee::getName)
            //收集数据,并存放到HashSet中,有去重功能
            .collect(Collectors.toCollection(HashSet::new));
    hs.forEach(System.out::println);
    //总数
    Long count = employees.stream()
            .collect(Collectors.counting());
    System.out.println(count);

    System.out.println("-----------------------------");

    //平均值
    Double avg = employees.stream()
            //工资的平均值
            .collect(Collectors.averagingDouble(Employee::getSalary));
    System.out.println(avg);

    System.out.println("-----------------------------");

    //总和
    Double sum = employees.stream()
            .collect(Collectors.summingDouble(Employee::getSalary));
    System.out.println(sum);

    //最大值
    Optional<Employee> max = employees.stream()
            .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
    System.out.println(max.get());

    //最小值
    Optional<Double> min = employees.stream()
            .map(Employee::getSalary)
            .collect(Collectors.minBy(Double::compare));
    System.out.println(min.get());
   //分组
    Map<Employee.Status, List<Employee>> map = employees.stream()
            //按照状态分组
            .collect(Collectors.groupingBy(Employee::getStatus));
    System.out.println(map);

    //多级分组
    Map<Employee.Status, Map<String, List<Employee>>> map2 = employees.stream()
            //按状态分组后再按照年龄分
            .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                if (e.getAge() <= 35) {
                    return "青年";
                } else if (e.getAge() <= 50) {
                    return "中年";
                } else {
                    return "老年";
                }
            })));
    System.out.println(map2);
    //分区
    Map<Boolean, List<Employee>> map = employees.stream()
            //满足条件true一个区,不满足条件false一个区
            .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
    System.out.println(map);

    //计算
    DoubleSummaryStatistics dss = employees.stream()
            .collect(Collectors.summarizingDouble(Employee::getSalary));
    System.out.println(dss.getCount());
    System.out.println(dss.getAverage());
    System.out.println(dss.getMax());
    System.out.println(dss.getMin());

    //连接
    String s = employees.stream()
            .map(Employee::getName)
            .collect(Collectors.joining());
//                .collect(Collectors.joining(", "));
//                .collect(Collectors.joining(", ", "====", "===="));
    System.out.println(s);

并行流与顺序流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
RecursiveAction没有返回值
RecursiveTask有返回值

三、Optional

在这里插入图片描述
在这里插入图片描述

四、接口中的默认方法与静态方法

在这里插入图片描述
在这里插入图片描述

public class Test {
    public static void main(String[] args) {
        //当某个类继承和实现的类中存在相同的方法时,如果父类中提供了具体实现,优先父类
        //如果实现的两个接口都有相同的方法,必须重写其中一个接口的方法
        SubClass subClass = new SubClass();
        System.out.println(subClass.getName()); //class

        MyFun.show();
    }
}

interface MyFun{
    default String getName(){
        return "interface";
    }

    //接口中可以写静态方法
    public static void show(){
        System.out.println("interface static method");
    }
}

class MyClass{
    public String getName(){
        return "class";
    }
}

class SubClass extends MyClass implements MyFun {
}

五、新时间日期API

在这里插入图片描述

LocalDate、LocalTime、LocalDateTime

  • LocalDate:日期
  • LocalTime:时间
  • LocalDateTime:日期时间

三个类用法相同,只是专注点不同。

	//获取当前时间
	LocalDateTime ldt = LocalDateTime.now();
	System.out.println(ldt);    //2020-08-09T22:19:45.912
	//获取指定时间,2020-01-01 00:00:00
	LocalDateTime ldt2 = LocalDateTime.of(2020, 1, 01, 00, 00, 00);
	System.out.println(ldt2);   //2020-01-01T00:00
	
	//plusXxx()方法为在当前时间上增加时间
	LocalDateTime ldt3 = ldt2.plusYears(2);
	System.out.println(ldt3);   //2022-01-01T00:00
	
	System.out.println(ldt2.getYear());         //年 2020
	System.out.println(ldt2.getMonthValue());   //月 1
	System.out.println(ldt2.getDayOfMonth());   //日 1
	System.out.println(ldt2.getHour());         //时 0
	System.out.println(ldt2.getMinute());       //分 0
	System.out.println(ldt2.getSecond());       //秒 0

Instant

Instant:时间戳(以Unix元年(1970-01-01 00:00:00)到某个时间之间时间的毫秒值)

    Instant instant = Instant.now();    //默认获取 UTC 时区
    System.out.println(instant);    //2020-08-09T14:19:45.914Z

    //偏移8个小时
    OffsetDateTime odt = instant.atOffset(ZoneOffset.ofHours(8));
    System.out.println(odt);    //2020-08-09T22:19:45.914+08:00

    //转成毫秒时间戳
    System.out.println(instant.toEpochMilli()); //1596983036271

    Instant instant2 = Instant.ofEpochSecond(60);
    System.out.println(instant2);   //1970-01-01T00:01:00Z

Duration、Period

  • Duration:计算两个"时间"的间隔
  • Period:计算两个"日期"的间隔
    //Duration:计算两个"时间"的间隔
    Instant ins1 = Instant.now();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Instant ins2 = Instant.now();
    Duration duration = Duration.between(ins1, ins2);
    System.out.println(duration.toMillis());

    LocalTime lt1 = LocalTime.now();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    LocalTime lt2 = LocalTime.now();
    Duration duration2 = Duration.between(lt1, lt2);
    System.out.println(duration2.toMillis());


    //Period:计算两个"日期"的间隔
    LocalDate ld1 = LocalDate.of(2020, 1, 1);
    LocalDate ld2 = LocalDate.now();
    Period period = Period.between(ld1, ld2);
    //相差7个月8天
    System.out.println(period.getYears());  //0
    System.out.println(period.getMonths()); //7
    System.out.println(period.getDays());   //8

时间校正器

在这里插入图片描述

TemporalAdjuster:时间校正器

    //TemporalAdjuster:时间校正器
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println(ldt);    //2020-08-10T11:09:16.967

    //withXxx():
    LocalDateTime ldt2 = ldt.withDayOfMonth(10);
    System.out.println(ldt2);   //2020-08-10T11:09:16.967

    //返回下一个周日的日期时间
    LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
    System.out.println(ldt3);   //2020-08-16T11:09:16.967

    //自定义:返回下一个工作日的日期时间
    LocalDateTime ldt5 = ldt.with((l) -> {
        LocalDateTime ldt4 = (LocalDateTime) l;
        //获取当前为周几
        DayOfWeek dow = ldt4.getDayOfWeek();

        //如果是周五,日期加上3天
        if (dow.equals(DayOfWeek.FRIDAY)) {
            return ldt4.plusDays(3);
        } else if (dow.equals(DayOfWeek.FRIDAY)) {
            //如果是周五,日期加上1天
            return ldt4.plusDays(2);
        } else {
            //其他的加1天
            return ldt4.plusDays(1);
        }
    });
    System.out.println(ldt5);   //2020-08-11T11:17:36.618

DateTimeFormatter:格式化时间/日期

    //DateTimeFormatter:格式化时间/日期
    DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
    LocalDateTime ldt = LocalDateTime.now();
    //格式化日期
    String strDate = ldt.format(dtf);
    System.out.println(strDate);    //2020-08-10

    //自定义:日期格式
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String strDate2 = dtf2.format(ldt);
    System.out.println(strDate2);   //2020年08月10日 11:24:53

    //转换为原来的日期
    LocalDateTime newDate = ldt.parse(strDate2, dtf2);
    System.out.println(newDate);    //2020-08-10T11:27:28

ZonedDateTime:时区

在这里插入图片描述
在这里插入图片描述

    //支持的时区
    Set<String> set = ZoneId.getAvailableZoneIds();
    set.forEach(System.out::println);

    //指定时区的日期时间
    LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
    System.out.println(ldt);    //2020-08-10T12:34:06.619

    //指定时区的日期时间,返回带时区的日期时间
    LocalDateTime ldt2 = LocalDateTime.now();
    ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Tokyo"));
    System.out.println(zdt);    //2020-08-10T11:36:39.001+09:00[Asia/Tokyo]

六、重复注解与类型注解

在这里插入图片描述
注解:MyAnnotation

@Repeatable(MyAnnotations.class)    //重复注解需要加上@Repeatable注解修饰,并指定注解的容器
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})  //注解可加的位置(TYPE_PARAMETER:类型注解)
@Retention(RetentionPolicy.RUNTIME) //注解的生命周期
public @interface MyAnnotation {

    String value() default "angenin";

}

注解的容器:MyAnnotations

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})  //注解可加的位置
@Retention(RetentionPolicy.RUNTIME) //注解的生命周期
public @interface MyAnnotations {

    //MyAnnotation的注解容器
    MyAnnotation[] value();

}

测试类:TestAnnotation

public class TestAnnotation {

    //@NotNull(类型注解):对象不能为空
    private @NotNull Object obj = null;

    @MyAnnotation("hello")
    @MyAnnotation("world")
    public void show(@MyAnnotation("abc") String str){
    }

    public static void main(String[] args) throws Exception {
        Class<TestAnnotation> clazz = TestAnnotation.class;
        Method m1 = clazz.getMethod("show");

        MyAnnotation[] mas = m1.getAnnotationsByType(MyAnnotation.class);

        for (MyAnnotation ma : mas) {
            System.out.println(ma.value());
        }
    }
}

JDK1.8的新特性可能并不完整,按照视频记的笔记,目前正在查漏补缺。

学习视频:https://www.bilibili.com/video/BV14W411u7Ly?p=1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值