JDK1.8新特性知识详解

jdk1.8新特性汇总如下图JDK1.8新特性知识详解_第1张图片

核心/常用知识点

函数式编程(Lambda表达式)

特点

它不是一种具体的技术,是一种方法论,使用对应提供的函数进行编程,而不是去关心内部的实现。

使用格式

1·方法没有参数:()->{ }
2·方法有参数:(参数,参数)->{ }
3·如果现在只有一行语句返回:(参数,参数)->语句

内置函数接口

JDK1.8新特性知识详解_第2张图片

Consumer 函数式接口(消费型)

  • 作用
    接受单个输入参数并且不返回结果的操作,与大多数其他功能接口不同, Consumer预期通过副作用进行操作。
  • 源码
    下面展示一些 内联代码片
/**
 * 接受单个输入参数并且不返回结果的操作。
 * 与大多数其他功能接口不同, Consumer预期通过副作用进行操作。
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer {

    /**
     * 对给定的参数执行此操作。
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * 返回一个组合的Consumer ,依次执行此操作,然后执行after操作。 
     * 如果执行任一操作会抛出异常,它将被转发到组合操作的调用者。 
     * 如果执行此操作会引发异常,则不会执行after操作。
     *
     * @param 此操作后执行的操作
     * @return 一个组成的 Consumer ,依次执行 after操作
     * @throws NullPointerException - if after is null
     */
    default Consumer andThen(Consumer after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
  • 示例代码
    /**
     * 获取一个新的字符串
     * @param name
     * @param consumer
     */
    public static void getNewStr(String name,Consumer consumer){
        consumer.accept(name);
    }
    
    public static void main(String[] args) {
       String name = "张三";
       getNewStr(name,(x)-> System.out.println(x+"去吃饭了..."));
       //输出结果为:张三去吃饭了...
    }
    
    从上述示例可以看出,这个函数相当于预先给你一些默认的操作,如果只要传入相对应的参数进去就能自动帮你实现功能。

Function 函数(转换型)

  • 作用
    Function接口 接受一个输入参数T,返回一个结果R。
  • 源码
    下面展示一些 内联代码片
@FunctionalInterface
public interface Function {
    // 接受输入参数,对输入执行所需操作后  返回一个结果。
    R apply(T t);

    // 返回一个 先执行before函数对象apply方法,再执行当前函数对象apply方法的 函数对象。
    default  Function compose(Function before) {
       Objects.requireNonNull(before);
       return (V v) -> apply(before.apply(v));
    }

    // 返回一个 先执行当前函数对象apply方法, 再执行after函数对象apply方法的 函数对象。
    default  Function andThen(Function after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }   

    // 返回一个执行了apply()方法之后只会返回输入参数的函数对象。
    static  Function identity() {
        return t -> t;
    } 
}
  • 示例代码
 /**
     * 获取一个新的价格
     * @param price
     * @param function
     * @return
     */
    static Double getNewPrice(Float price, Function function){
        return function.apply(price);
    }

    public static void main(String[] args) {
        Double newPrice = getNewPrice(20.36F, (x) -> (double) x + 30);
        System.out.println(newPrice);
        //输出结果为:50.36000061035156
    }
  • 总结
    从上面示例可以看出,function 提供的是一个转换型的功能,数据类型转换。
  • andThen 使用
    – 示例代码
 /**
     * 从参数可知,function 第一次已经将float转换成double了,第二次将double转换成float
     * 本示例是告诉用法,不要以为是没事转换来转换去
     * @param price
     * @param function
     * @param function2
     * @return
     */
    static Float getNewPrice(Float price, Function function,Function function2){
        return function.andThen(function2).apply(price);
    }

    public static void main(String[] args) {
        Float newPrice = getNewPrice(20.36F, (x) -> (double) x + 30,(x)->(float)(x + 20) );
        System.out.println(newPrice);

    }

Supplier 函数(供给型)

  • 作用
    获取一个结果
  • 源码
@FunctionalInterface
public interface Supplier {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
  • 示例代码
public static String getNewStr(Supplier supplier){
        return supplier.get();
    }

    public static void main(String[] args) {
        String name = "张三";
        String newStr = getNewStr(()->name+"去吃饭了...");
        System.out.println(newStr);
        //输出结果为:张三去吃饭了...
    }
  • 总结
    supplier供给型明显和consumer消费型不相同,虽然输出结果都是一样,使用起来也不一样,supplier是有返回结果的,consumer 是没有返回结果的

Predicate 断言式 函数(判断型)

  • 作用
  • 源码
	/**
     * 执行返回结果
     */
    boolean test(T t);

    /**
 	 * 多条件同时满足
     */
    default Predicate and(Predicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
	 * 执行结果的反转值
	 * true变成 false ,false 变成true
     */
    default Predicate negate() {
        return (t) -> !test(t);
    }

    /**
     * 两个条件或者
     */
    default Predicate or(Predicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
	 * 是否是同一对象
     */
    static  Predicate isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
  • 示例代码
/**
     * 获取断言信息
     * @param value
     * @param predicate
     * @return
     */
    public static Boolean getPredicate(Integer value, Predicate predicate){
        return predicate.test(value);
    }

    public static void main(String[] args) {
        Integer math = 20 ;
        Boolean predicate = getPredicate(math, (x) -> x >= 30);
        System.out.println(predicate);
    }
  • 总结
    用于校验条件是否满足情况。

Comparator排序

  • 示例代码
    public static void main(String[] args) {
        List studentList = Arrays.asList(new Student("张三", 7, 90.00),
                new Student("李四", 6, 80.05),
                new Student("王五", 3, 100.00));
        //多线程并发情况下能保证线程安全
        Collections.synchronizedList(studentList)
        //按成绩进行倒叙排列
        Collections.sort(studentList,Comparator.comparing(Student::getGrade).reversed());
        //遍历新的集合顺序
        studentList.forEach(student->{
            System.out.println(student.toString());
        });
        //输出结果为:
       		//王五年龄是 :3, 分数是:100.0分
			//张三年龄是 :7, 分数是:90.0分
			//李四年龄是 :6, 分数是:80.05分
    }

    @Data
    @AllArgsConstructor
    public static class Student{
        private String name;
        private Integer age;
        private Double grade;

        @Override
        public String toString() {
            return  name + "年龄是 :" + age + ", 分数是:" + grade + '分';
        }
    }

易于并发编程 parallel()

比如在一堆数字中寻找最小值

当这堆数字很大的时候,我们需要去实现多线程去比较的话,需要考虑多线程,线程池以及拆分数据,实现快排等,但是当我们使用JDK8函数式编程的时候可以直接使用一个方法开启 并行 .parallel()

int min = IntStream.of(nums).parallel().min().getAsInt();

比较下函数式编程和命令式编程

  • 函数式编程
int min = IntStream.of(nums).parallel().min().getAsInt();
  • 命令式编程
	int minNum = Integer.MAX_VALUE;
    for (int num : nums) {
        if (num < minNum) {
            minNum = num;
        }
    }

通过上述函数式编程优势很明显,不需要处理内部是怎么实现的,只需要得到一个结果就行了。

Option类

作用

Optional 可以省去非空判断,因为内部已经实现了,避免了空指针异常。

常用方法

方法 描述
of 把指定的值封装为Optional对象,如果指定的值为null,则抛出NullPointerException
empty 创建一个空的Optional对象
ofNullable 把指定的值封装为Optional对象,如果指定的值为null,则创建一个空的Optional对象
get 如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException
orElse 如果创建的Optional中有值存在,则返回此值,否则返回一个默认值
orElseGet 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值
orElseThrow 如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常
filter 如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象
map 如果创建的Optional中的值存在,对该值执行提供的Function函数调用
flagMap 如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象
isPresent 如果创建的Optional中的值存在,返回true,否则返回false
ifPresent 如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做

默认方法(@FunctionalInterface )

默认方法的作用

这个新特性其实是很重要的,它的作用就是在接口上可以定义方法的实现 作为默认方法,这样
Java就可以扩展很多底层接口 比如List接口 ,对其添加了很多default默认方法,这时候List的接口的实现类也不用去修改了。

特点

  • 一个类实现多个接口,因此可以采用实现多个接口的方式实现多重继承的目的。
  • 接口中成员的修饰符都是public或者default,不能使用private和protected修饰。
  • 接口可以默认方法与静态方法,有方法体的实现。但abstract修饰的抽象方法没有方法体。
  • 标识接口
    Java语言中,有些接口内部没有声明任何方法,也就是实现这些接口不需要重写任何方法,这些没有任何方法声明的接口叫做标识接口。比如clonable和Serializable接口等,表示实现它的类属于一个特定的类型。

示例代码

@FunctionalInterface
interface Interface1 {
  int doubleNumber(int i);

  default void someMethod(){
    System.out.println("Interface1 default Method ");
 }
}

多重实现的默认方法冲突

@FunctionalInterface  
interface Interface1 {
  int doubleNumber(int i);
  void someMethod();
}

类型注解(ElementType)

含义:在各种程序元素(定义类、定义接口、定义方法、定义成员变量…)

ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。
ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。

重复注解

含义

标注在类,方法等上面的注解可以重复出现,之前是不允许

添加了新的getAnnotationsByType()

getAnnotationsByType(),可以返回某个类型的重复注解,例如Filterable.class.getAnnoation(Filters.class)将返回两个Filter实例,输出到控制台的内容如下所示:

filter1
filter2

LocalDateTime

类型推断

其他知识

JRE 精简

Permgen删除

StampedLock

JavaFx2.0

其他

你可能感兴趣的:(jdk,java,jdk1.8,jdk,Lambda,函数接口)