zl程序教程

您现在的位置是:首页 >  其它

当前栏目

JDK1.8新特性

特性 JDK1.8
2023-09-14 09:15:25 时间

目录

1.Lambda表达式

2.添加默认方法

3.Stream操作

4.Optional 类

5.Java时间API


Java8(又称为 jdk 1.8) 是 Java 语言开发迄今为止的一个最主要和用户最多的一个版本。Java8是Oracle公司于2014年3月18日发布 ,它不仅支持函数式编程,而且还拥有新的日期 API,Stream API 等操作。

1.Lambda表达式

Lambda 允许把函数作为一个方法的参数,使用Lambda表达式可以使代码变的更加简洁紧凑、简洁表达。

lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值((x1,x2))。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果函数主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回一个数值。
  • lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义,详细见如下案例)

lambda表达式的语法:

(parameters) -> expression
或
(parameters) ->{ statements; }

(x)->{system.out.prinln} //直接打印x参数; 

lambda表达式简单例子:

/**
 * lambda
 *
 */
public class Java8TestLambda {

    public static  void main(String [] args){
        CacualtePriceService cacualteAddPriceService=(x1,x2)->(x1+x2);
        CacualtePriceService cacualteSubPriceService=(x1,x2)->(x1-x2)
        
        System.out.println(cacualteAddPriceService.cacluatePrice(1.2f,2.2f));//3.4
        System.out.println(cacualteSubPriceService.cacluatePrice(3.2f,1.2f));//2.0
        System.out.println("------------------使用策略模式----------------------");
        System.out.println(operate(1.2f,2.2f,(x1,x2)->(x1+x2)));//3.4
        System.out.println(operate(3.2f,1.2f,(x1,x2)->(x1-x2)));//2.0
    }
    /**
     * 计算价格接口
     */
    interface CacualtePriceService{
        Float cacluatePrice(Float x1,Float x3);
    }

    static Float operate(float x1, float x2, CacualtePriceService cacualtePriceService){
       return cacualtePriceService.cacluatePrice(x1,x2);
    }
}

打印结果:

3.4
2.0
------------------使用策略模式----------------------
3.4
2.0

由上面的例子可知,Lambda可以简化函数接口(接口中只有一个方法,例如上述例子中CacualtePriceService接口)的实现方法。

  // static final float num=1.1f;
    public static  void main(String [] args){
        float num=1.1f;
        CacualtePriceService cacualteAddPriceService=(x1,x2)->(x1+x2+num);
        CacualtePriceService cacualteSubPriceService=(x1,x2)->(x1-x2+num);
        num=2;

    }
console://当修改num=2 时候会报错:
Error:(14, 70) java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量

当修改num=2 时候会报错:从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量。

2.添加默认方法

java 8添加了接口的默认方法,简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现的方法。

我们只需在方法名前面加个 default 关键字即为默认方法。

为什么要有这个特性?

之前的接口,当需要修改接口时候,需要修改全部实现该接口的类,然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法,目的是为了解决接口的修改与现有的实现不兼容的问题

默认方法案例如下:

/**
 * jdk 1.8 默认方法
 */
public class DafaultMethod {

    interface Car {
        static void staticRun() {
            System.out.println("测试汽车静态接口");
        }
        default void defaultRun() {
            System.out.println("测试汽车默认接口");
        }
        void run();
    }
    static class QicheCar implements Car {

        @Override
        public void run() {
            System.out.println("测试汽车实现接口");
            defaultRun();
            Car.staticRun();
        }
    }
    public static void main(String[] args) {
        QicheCar car = new QicheCar();
        car.run();
    }
}

输出内容:

测试汽车实现接口
测试汽车默认接口
测试汽车静态接口

由上述案例可知,接口直接可以调用静态方法以及默认方法。

3.Stream操作

要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选,排序,聚合等操作。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。Java中的Stream并不会存储元素,而是按需计算。

数据源中流的来源 可以是集合,数组,I/O channel, 产生器generator 等。

(1)Stream基本操作

一、获取流

1.1 所有的 Collection 集合都可以通过 stream 默认方法获取流

1.2 Stream 接口的静态方法 of 可以获取数组对应的流。

二、中间操作

1.过滤 filter 
2.去重 distinct 
3.排序 sorted 
4.截取 limit
5.跳跃 skip 
6.转换map/flatMap 
7.其他 peek

三、终止操作

1、循环 forEach
2、计算 min、max、count、 average
3、匹配 anyMatch、 allMatch、 noneMatch、findFirst、 findAny
4、汇聚 reduce
5、收集器 toArray collect
 

4.Optional 类

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

5.Java时间API

Java 8 在 java.time 包下提供了很多新的 API 。两个比较重要的 API:Local(本地) − 简化了日期时间的处理,没有时区的问题。Zoned(时区) − 通过制定的时区处理日期时间。

具体案例参考如下:

 public void testLocalDateTime(){
        // 获取当前时间
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);//2021-06-29T16:27:58.543
        // 获取指定时间
        LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
        System.out.println(ld2);//2016-11-21T10:10:10
        // 指定时间后移动2年
        LocalDateTime ldt3 = ld2.plusYears(20);
        System.out.println(ldt3);//2036-11-21T10:10:10
        // 指定时间前移动2月
        LocalDateTime ldt4 = ld2.minusMonths(2);
        System.out.println(ldt4);//2016-09-21T10:10:10

        System.out.println(ldt.getYear());//2021
        System.out.println(ldt.getMonthValue());//6
        System.out.println(ldt.getDayOfMonth());//29
        System.out.println(ldt.getHour());//16
        System.out.println(ldt.getMinute());//27
        System.out.println(ldt.getSecond());//58

        System.out.println("---------------当前时间解析-------------------");

        // 当前时间解析
        LocalDateTime currentTime = LocalDateTime.now();
        System.out.println("当前时间: " + currentTime);//2021-06-29T16:27:58.546

        LocalDate date1 = currentTime.toLocalDate();
        System.out.println("date1: " + date1);// 2021-06-29

        Month month = currentTime.getMonth();
        Integer mon=month.ordinal()+1;
        int day = currentTime.getDayOfMonth();
        int seconds = currentTime.getSecond();

        System.out.println("月: " + month +"/"+mon+", 日: " + day +", 秒: " + seconds);//月: JUNE/6, 日: 29, 秒: 58

        LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
        System.out.println("date2: " + date2);//date2: 2012-06-10T16:27:58.546

        // 12 december 2014
        LocalDate date3 = LocalDate.of(2014, Month.FEBRUARY, 25);
        System.out.println("date3: " + date3);//date3: 2014-02-25

        // 22 小时 15 分钟
        LocalTime date4 = LocalTime.of(22, 15);
        System.out.println("date4: " + date4);//date4: 22:15

        // 解析字符串
        LocalTime date5 = LocalTime.parse("20:15:30");
        System.out.println("date5: " + date5);//date5: 20:15:30
        System.out.println("-------------Instant : 时间戳--------------------");
        // Instant : 时间戳。 (使用 Unix 元年  1970年1月1日 00:00:00 所经历的毫秒值)
        Instant ins = Instant.now();  //默认使用 UTC 时区 比大陆时间提前8小时
        System.out.println("ins"+ins);//ins2021-06-29T08:27:58.578Z

        OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
        System.out.println("odt"+odt);//odt2021-06-29T16:27:58.578+08:00

        System.out.println("ins.getNano():"+ins.getNano());//ins.getNano():578000000

        Instant ins2 = Instant.ofEpochSecond(5);
        System.out.println("ins2:"+ins2);//ins2:1970-01-01T00:00:05Z


        System.out.println("----------耗费时间统计------------");
        Instant ins1 = Instant.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        Instant ins3 = Instant.now();

        System.out.println("所耗费时间为:" + Duration.between(ins1, ins3));//所耗费时间为:PT1.005S
        
        LocalDate ld3 = LocalDate.now();
        LocalDate ld4 = LocalDate.of(2011, 1, 1);

        Period pe = Period.between(ld4, ld3);
        System.out.println(pe.getYears());//10
        System.out.println(pe.getMonths());//5
        System.out.println(pe.getDays());//28

    }

参考文章:

https://www.runoob.com/

JDK1.8新特性 - 知乎

Stream流的基本操作_摘星大师的博客-CSDN博客_stream流操作方法