JDK16即将发布,你准备好了吗?JDK8新特性Lambda

      岁月无声,岁月有声.2020实鼠不易,2021牛转乾坤。

      当我们开发者与大多企业还停留在JDK8的时候,JDK16即将问世,你准备好了吗?

作为开发者的我与大家一样,我真心的跟不上,也跟不上jdk更新的速度,但这会影响我们吗?答案是否定的,目前主流大型企业很多停留在jdk6,jdk7与jdk8,jdk9这几个主流版本。所以对于我们而言,也可暂时不去更新学习jdk16。当然,具体情况根据自身需求情况,有需要就可以去学习,暂时不影响工作,也未必马上就去学习。当然,作为程序员的我们,是需要经常学习的,学海无涯,活到老学到老。有梦想就去追逐,即使失败,也无愧于心。那么在这里,博主并不会去介绍jdk16,博主这里主要是介绍jdk8相关的知识特性。

1、JDK8新特性简介

  • 速度更快:算法的优化(比如HashMap)、底层内存结构的优化(将永久区PremGen变成了元空间MetaSpace)
  • 代码更少(增加了新的语法Lambda表达式)
  • 强大的Stream API
  • 偏于并行
  • 最大化减少空指针异常 Optional
    tips:
    永久区属于堆heap(在jdk1.7之前,heap中分为了2个区:垃圾回收区和永久区);而元空间存储在物理内存上

2、函数式编程思想

  • 在数学中,函数指的是给定一个输入值,通过一套计算方案,最终给出结果值。 也就是拿什么东西做什么事。
  • 面向对象又过分的强调了必须要通过对象的形式来做某事。(重视做事的过程)
  • 而函数式编程强调“做什么,而不是以什么形式去做”。(重视做事的结果)

3、Lambda编程基础

3.1函数式接口

在学习Lambda之前,需要先搞清楚函数式接口
函数式接口:适用于函数式编程场景(Lambda表达式),接口中有且仅有一个抽象方法,且需要添加FunctionalInterface注解
示例代码如下:

@FunctionalInterface
interface Conver{
	void fun();
}

3.2Lambda表达式格式及说明

Lambda表达式的标准格式为: (参数类型 参数名称) ‐> { 代码语句 }
说明:

  • 小括号内的语法与传统方法参数列表一致
  • -> 是新引入的语法格式,代表指向动作 ,表示小括号前面的参数被用于后面{}里面的代码语句
  • 大括号内的语法与传统方法体要求基本一致,它实际上是对函数式接口里唯一的那个抽象方法的重写

3.3Lambda省略格式

Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。
省略规则如下:

  • 小括号内参数的类型可以省略;
  • 如果小括号内有且仅有一个参,则小括号可以省略;
  • 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

3.4代码实例

1)无参无返回值

import org.junit.Test;
public class demo01 {
    @Test
    public void demo01(){
        //匿名内部类写法
        Runnable task = new Runnable() {
            @Override
            public void run() {
                System.out.println("多线程任务1");
            }
        };
        new Thread(task).start();

        //Lambda写法
        new Thread(()->{System.out.println("多线程任务2");}).start();
        //{}里面只有一条语句,可以省略{}和;
        new Thread(()->System.out.println("多线程任务3")).start();
    }
}

2)有参有返回值

//有参有返回值
//有参有返回值
@FunctionalInterface
public interface addSum {
    int sum(int a,int b);
}
package com.demo.lambda.day03;

import org.junit.Test;

public class LambdaAddSumDemo {
    @Test
    public void demo02() {
        //需求:求两个整数和
        //int result = addSum(10,20,(a,b)->{return a+b;});
        //可优化为下面代码
        int result = sum(10,20,(a,b)->a+b);
        System.out.println(result);
    }

    //两个int类型进行处理
    public int sum(int a,int b,addSum c){
        return c.sum(a,b);
    }
}

3)参数、返回值类型为函数式接口类型

package com.demo.lambda.day03;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;

public class demo03 {
    @Test
    public void demo03() {
        //需求1:执行1个线程任务
        startThread(()->System.out.println("多线程"));

        //需求2:将数组按照由小到大顺序排序
        String[] arr = {"c","a","d","b"};
        Arrays.sort(arr,compara());
        System.out.println(Arrays.toString(arr));
    }

    //参数为函数式接口,执行1个线程操作
    public void startThread(Runnable target){
        new Thread(target).start();
    }

    //返回值类型为一个函数式接口,返回一个比较器对象
    public Comparator<String> compara(){
        return (a,b)->a.compareTo(b);
    }

}

3.5Lambda的延迟执行

有些场景代码执行后,结果不一定会使用,这就造成了性能浪费。而Lambda具有延迟执行的特性,就可以很好的解决这个问题。
参考代码如下:

package com.demo.lambda.day03;

import org.junit.Test;

public class LambdaStringDemo {
    @Test
    public void demo04() {
        String msg1 = "hello";
        String msg2 = "world";
        //不论level,在调用log方法的时候,后面的参数一定要进行拼接操作
        log("2",msg1+msg2);

        //只有当level符合条件,才会去调用append方法,才会执行Lambda
        newLog("1",()->msg1+msg2);
    }

    //记录日志
    public void log(String level,String msg){
        if("1".equals(level)){
            System.out.println(msg);
        }
    }

    public void newLog(String level,MessageBuilder mb){
        if("1".equals(level)){
            System.out.println(mb.append());
        }
    }
}

4、Lambda编程进阶

公共定义的函数式接口
从jdk1.8开始提供了function包,该包针对于用户有可能做的函数式接口做了一个公共定义
最为核心的有四个接口:

  1. 功能性接口:Function<T, R>
    是对接收一个T类型参数,返回R类型的结果的方法的抽象
    抽象方法:R apply(T t)
    默认方法:andThen
    示例代码如下:
package com.demo.lambda.day03;

import org.junit.Test;

import java.util.function.Function;

public class demo5 {
    @Test
    public void functionTest() {
        int num = fun("100",s->Integer.parseInt(s) );//字符串转成int类型
        System.out.println(num);
        //先将字符串转成int,再*10
        int result = method("5", s->Integer.parseInt(s), a->a *= 10);
        System.out.println(result);
    }

    //用于字符串处理
    public Integer fun(String s, Function<String,Integer> fun){
        return fun.apply(s);
    }

    //andThen:先执行一次apply操作,然后将第一次执行apply操作后获得的返回值作为参数再执行一次apply操作
    public int method(String s, Function<String,Integer> one,Function<Integer,Integer> two){
        return one.andThen(two).apply(s);
    }
}

2. 消费型接口:Consumer<T>
对应的方法类型为接收一个参数,没有返回值
抽象方法:void accept(T t)
默认方法:andThen
示例代码如下:

package com.demo.lambda.day03;
import org.junit.Test;
import java.util.function.Consumer;
public class demo6 {
    @Test
    public void consumerTest(){
        shopping(12345, m->System.out.println("花了"+m+"元买了包包"));
        //将"hElLo"转成大写输出,其次再转成小写输出
        fun("hElLo",s->System.out.println(s.toUpperCase()),
                s->System.out.println(s.toLowerCase()));
    }

    //花钱购物
    public void shopping(double money,Consumer<Double> con){
        con.accept(money);
    }

    //andThen:使用提供的参数执行两次操作
    public void fun(String str, Consumer<String> one, Consumer<String> two){
        one.andThen(two).accept(str);
    }

}

3.供给型接口:Supplier<T>
该接口对应的方法类型不接受参数,但是提供一个返回值
抽象方法:T get()
示例代码如下:

package com.demo.lambda.day03;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
public class demo7 {
    @Test
    public void supplierTest(){
        //获取10个0~99之间的随机数
        List<Integer> list = getList(10, ()->new Random().nextInt(100));
        System.out.println(list);
    }

    //获取指定个数的Integer集合
    public List<Integer> getList(int count, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for(int i=0;i<count;i++){
            list.add(sup.get());
        }
        return list;
    }

}

4.断言型接口:Predicate<T>
该接口对应的方法为接收一个参数,返回一个Boolean类型
抽象方法:boolean test(T t)
默认方法:and(与),or(或),negate(非)
示例代码如下: 

package com.demo.lambda.day03;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class demo8 {
    @Test
    public void predicateTest(){
        List<String> list = Arrays.asList("Tom","Jerry","Tony");
        List<String> nl = filterList(list, s->s.startsWith("T"));//将所有以“T”开头的字符串放入集合中
        System.out.println(nl);

        //判断一个字符串既包含"H",又包含"O"
        boolean bool = andFun(s->s.contains("H"),s->s.contains("O"),"HelloOpen");
        System.out.println(bool);

        //判断一个字符串中是否含有"H"或者"O"
        bool = orFun(s->s.contains("H"),s->s.contains("O"),"HelloOpen");
        System.out.println(bool);

        //对给定操作进行非判定
        bool = negateFun(s->s.length()<5,"helloworld");
        System.out.println(bool);
    }

    //将满足条件的字符串放入集合中
    public List<String> filterList(List<String> list, Predicate<String> pre){
        List<String> nl = new ArrayList<>();
        for(String s:list){
            if(pre.test(s)){
                nl.add(s);
            }
        }
        return nl;
    }

    //and
    public boolean andFun(Predicate<String> one,Predicate<String> two,String s){
        return one.and(two).test(s);
    }

    //or
    public boolean orFun(Predicate<String> one,Predicate<String> two,String s){
        return one.or(two).test(s);
    }

    //negate
    public boolean negateFun(Predicate<String> pre, String s){
        return pre.negate().test(s);
    }

}

附:一些常用的其它接口

注:参考引用文献:

https://blog.csdn.net/u010572176/article/details/104393869

猜你喜欢

转载自blog.csdn.net/qq_30764991/article/details/113056903