jdk1.8新特性

本文详细介绍了JDK1.8中的Lambda表达式、函数式接口、方法引用、构造器调用以及StreamAPI,包括并行流、Fork/Join框架的应用,以及Optional容器的使用,同时提到了新的日期API和解耦合的概念。
摘要由CSDN通过智能技术生成

jdk1.8新特性

Lambda表达式

lambda表达式本质上是一段匿名内部类,也可以是一段可以传递的代码,其优点有以下几点:

1.简洁代码:使繁杂的代码简洁化,极大减少代码量

其缺点也有:

1.读起来不方便

函数式接口

函数式接口的提出是为了给lambda表达式的使用提供更好的支持。

什么是函数式接口?

函数式接口就是只定义了一个抽象方法的接口(Object类的public方法除外),并且还提供了注解:@FunctionalInterface

常见的四大函数式接口:

1.Consumer< T > :消费型接口,有参无返回值

  1. Supplier< T >:供给型接口,无参有返回值

  2. Function< T >:函数式接口,有参有返回值

  3. Predicate< T >:断言型接口,有参有返回值,返回值是boolean类型

方法引用和构造器调用

方法引用有三种表现形式:

1.对象::实列方法名

2.类::静态方法名

3.类::实列方法名

构造器引用:ClassName::new

数组引用:Type[]::new

Stream API

内置许多API可以有效的链式编程,让代码简洁

1.创建stream

1.校验通过Collection 系列集合提供的stream()或者paralleStream():list.stream(); ​ 2.通过Arays的静态方法stream()获取数组流:Arrays.stream(数组) ​ 3.通过Stream类中的静态方法of:Stream.of("ss","dd") ​ 4.创建无限流--迭代:Stream.iterate(0,(x)->x+2) 0:从多少开始 x:参数名 x+2:按照什么方式迭代

2.中间操作

1.筛选:filter 过滤:limit 去重:distinct 遍历:forEach ​ 2.生成新的流 通过map映射:emps.stream.map((e)->e.getAge()).forEach(System.out.println); ​ 3.自然排序:emps.stream.sorted(e1,e2) ->{排序规则,利用compareTo进行排序}

3.终止操作

1.allMatch :检查是否匹配所有元素 ​ 2.anyMatch :检查是否至少匹配一个元素 ​ 3.noneMatch:检查是否没有匹配所有元素 ​ 4.findFirst:返回第一个元素 ​ 5.findAny:返回当前流中的任意元素 ​ 6.count:返回流中元素的总个数 ​ 7.max:返回流中最大值 ​ 8.min:返回流中最小值 ​ 9.reduce:可以将流中元素反复结合起来,得到一个值 ​ 10.Collect:将流转换为其他形式,接收一个Collection接口的实现,用于给Stream中元素做汇总的方法

/**
         *      查找和匹配
         *          allMatch-检查是否匹配所有元素
         *          anyMatch-检查是否至少匹配一个元素
         *          noneMatch-检查是否没有匹配所有元素
         *          findFirst-返回第一个元素
         *          findAny-返回当前流中的任意元素
         *          count-返回流中元素的总个数
         *          max-返回流中最大值
         *          min-返回流中最小值
         */
​
        /**
         *  检查是否匹配元素
         */
        boolean b1 = emps.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
​
        boolean b2 = emps.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
​
        boolean b3 = emps.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);
​
        Optional<Employee> opt = emps.stream()
                .findFirst();
        System.out.println(opt.get());
​
        // 并行流
        Optional<Employee> opt2 = emps.parallelStream()
                .findAny();
        System.out.println(opt2.get());
​
        long count = emps.stream()
                .count();
        System.out.println(count);
​
        Optional<Employee> max = emps.stream()
                .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(max.get());
​
        Optional<Employee> min = emps.stream()
                .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min.get());
​
         /**
         *  reduce :规约操作
         */
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer count2 = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(count2);
​
        Optional<Double> sum = emps.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(sum);
​
        /**
         *  collect:收集操作
         */
​
        List<Integer> ageList = emps.stream()
                .map(Employee::getAge)
                .collect(Collectors.toList());
        ageList.stream().forEach(System.out::println);

并行流和串行流 在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流。并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容。Stream api中声明可以通过parallel()与sequential()方法在并行流和串行流之间进行切换。 jdk1.8并行流使用的是fork/join框架进行并行操作

ForkJoin框架 Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总。 关键字:递归分合、分而治之。 采用 “工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线 程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的 处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因 无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果 某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子 问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程 的等待时间,提高了性能.。

/**
 * 要想使用Fark—Join,类必须继承
 * RecursiveAction(无返回值)
 * Or
 * RecursiveTask(有返回值)
*
*/
public class ForkJoin extends RecursiveTask<Long> {
​
    /**
     * 要想使用Fark—Join,类必须继承RecursiveAction(无返回值) 或者
     * RecursiveTask(有返回值)
     *
     * @author Wuyouxin
     */
    private static final long serialVersionUID = 23423422L;
​
    private long start;
    private long end;
​
    public ForkJoin() {
    }
​
    public ForkJoin(long start, long end) {
        this.start = start;
        this.end = end;
    }
​
    // 定义阙值
    private static final long THRESHOLD = 10000L;
​
    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            long sum = 0;
            for (long i = start; i < end; i++) {
                sum += i;
            }
            return sum;
        } else {
            long middle = (end - start) / 2;
            ForkJoin left = new ForkJoin(start, middle);
            //拆分子任务,压入线程队列
            left.fork();
            ForkJoin right = new ForkJoin(middle + 1, end);
            right.fork();
​
            //合并并返回
            return left.join() + right.join();
        }
    }
​
    /**
     * 实现数的累加
     */
    @Test
    public void test1() {
        //开始时间
        Instant start = Instant.now();
​
        //这里需要一个线程池的支持
        ForkJoinPool pool = new ForkJoinPool();
​
        ForkJoinTask<Long> task = new ForkJoin(0L, 10000000000L);
        // 没有返回值     pool.execute();
        // 有返回值
        long sum = pool.invoke(task);
​
        //结束时间
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).getSeconds());
    }
​
    /**
     * java8 并行流 parallel()
     */
    @Test
    public void test2() {
        //开始时间
        Instant start = Instant.now();
​
        // 并行流计算    累加求和
        LongStream.rangeClosed(0, 10000000000L).parallel()
                .reduce(0, Long :: sum);
​
        //结束时间
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).getSeconds());
    }
​
    @Test
    public void test3(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        list.stream().forEach(System.out::print);
​
        list.parallelStream()
            .forEach(System.out::print);
    }
    //多线程展示
    @Test
    public void test(){
        // 并行流 多个线程执行
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        numbers.parallelStream()
                .forEach(System.out::print);
​
        //
        System.out.println("=========================");
        numbers.stream()
                     .sequential()
                     .forEach(System.out::print);
    }

Optional容器:使用Optional容器可以快速的定位NPE,并且在一定程度上可以减少对参数非空检验的代码量

/**
     *      Optional.of(T t); // 创建一个Optional实例
     *      Optional.empty(); // 创建一个空的Optional实例
     *      Optional.ofNullable(T t); // 若T不为null,创建一个Optional实例,否则创建一个空实例
     *      isPresent();    // 判断是够包含值
     *      orElse(T t);   //如果调用对象包含值,返回该值,否则返回T
     *      orElseGet(Supplier s);  // 如果调用对象包含值,返回该值,否则返回s中获取的值
     *      map(Function f): // 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty();
     *      flatMap(Function mapper);// 与map类似。返回值是Optional
     *
     *      总结:Optional.of(null)  会直接报NPE
     */
​
Optional<Employee> op = Optional.of(new Employee("zhansan", 11, 12.32, Employee.Status.BUSY));
        System.out.println(op.get());
​
        // NPE
        Optional<Employee> op2 = Optional.of(null);
        System.out.println(op2);
@Test
    public void test2(){
        Optional<Object> op = Optional.empty();
        System.out.println(op);
​
        // No value present
        System.out.println(op.get());
    }
@Test
    public void test3(){
        Optional<Employee> op = Optional.ofNullable(new Employee("lisi", 33, 131.42, Employee.Status.FREE));
        System.out.println(op.get());
​
        Optional<Object> op2 = Optional.ofNullable(null);
        System.out.println(op2);
       // System.out.println(op2.get());
    }
    @Test
    public void test5(){
        Optional<Employee> op1 = Optional.ofNullable(new Employee("张三", 11, 11.33, Employee.Status.VOCATION));
        System.out.println(op1.orElse(new Employee()));
        System.out.println(op1.orElse(null));
    }
​
    @Test
    public void test6(){
        Optional<Employee> op1 = Optional.of(new Employee("田七", 11, 12.31, Employee.Status.BUSY));
        op1 = Optional.empty();
        Employee employee = op1.orElseGet(() -> new Employee());
        System.out.println(employee);
    }
​
    @Test
    public void test7(){
        Optional<Employee> op1 = Optional.of(new Employee("田七", 11, 12.31, Employee.Status.BUSY));
        System.out.println(op1.map( (e) -> e.getSalary()).get());
    }
接口中的默认方法和静态方法

在接口中可以使用default和static关键字来修饰接口中定义的普通方法,注意如果方法与实现类的父类方法同名是优先继承父类的方法,即"类优先",如果实现两个同名方法的接口,必须手动声明默认实现哪个接口中的方法。

新时间日期API

新的日期API LocalDate | LocalTime | LocalDateTime 新的日期API都是不可变的,更使用于多线程的使用环境中

耦合:当资源包缺失,影响程序编译,解耦合就算可以解决这个问题,可以使除了该异常的其它功能可以正常运行,整个项目都可以编译通过

  • 37
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值