java 8新特性(一篇速通)

引言: 学完领悟java8新特性需要大概两三天,如果一天就学完可能啥也没记住

b站视频资源链接:关于java8的内容在列表最下面,大概三个多小时

为什么要学java8

java8(jdk1.8和java8是一个东西)对比于java7 新增了一些新语法特性 ,
自己开发用不用都可以,有时候可能还会会显得多此一举 , 有时候又很有用

主要是为了看懂别人的代码和为看懂源码排坑

接口增强

JDK 7 及以前只能定义全局常量和抽象方法

  • 全局变量 public static final
  • 抽象方法 public abstract

JDK 8 除了定义全局常量和抽象方法

还可以定义静态方法,默认方法

调用方式和普通方法一样(静态直接调 ,非静态需要new对象)如下

在这里插入图片描述

函数式接口

什么是函数式接口

如果一个接口中,只声明了一个抽象方法,就称该接口为函数式接口

如 Runnable接口只有run()方法 , Comparator接口只有accept()方法

可以加上@FunctionalInterface 标注一下

在这里插入图片描述

在这里插入图片描述


如何理解函数式接口

以及为什么要有函数式接口 : 面向函数编程

比如传统即使是静态方法,也需要先写在某个类里面,再调用;
函数式接口能让我们在需要这个函数的地方直接写这个函数,或直接在参数部分写这个函数,
比如(sort(Comparator) 需要什么方法就在括号里面写Comparator就是一个函数式接口)

在这里插入图片描述


java内置的四大函数式接口及案例

接下来的lanbda表达式

就是作为这些接口的实例化表达式使用,

在这里插入图片描述

对于需要以下四种类型的函数 直接调用函数式接口实现,没有重新写静态方法类的必要

在这里插入图片描述


传统写法写函数式接口: 定义需要传入方法的函数+匿名类实现方法

案例1: Consumer接口案例

定义:

在这里插入图片描述

传统写法如下:

在这里插入图片描述

接下来介绍的lambda方法方式:

在这里插入图片描述


案例2: predicate使用案例

public void Test8(){
    List<String> strings = Arrays.asList("背景", "北京", "南京", "天津");
    //传统写法  自定义predicate方法
    List<String> all = fillString(strings, new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.contains("京");
        }
    });
    System.out.println(all);
    // lambda写法 自定义predicate方法
    List<String> l2 = fillString(strings, s -> s.contains("京"));
    System.out.println(l2);
}

//定义一个对list判断的方法   
public List<String> fillString(List<String> list, Predicate<String> pre){
    ArrayList<String> strings = new ArrayList<>();
    for (String s : list) {
        if(pre.test(s)){
            strings.add(s);
        }
    }
    return strings;
}

下方lambda表达式内容将提供更多结合应用案例

其他接口

需要再查,主要是为了看懂别人的代码,自己用不用无所谓

在这里插入图片描述


Lanbda表达式

快速介绍

在这里插入图片描述

就是把重写函数方法的方式——>化简

以下是传统方法写函数式接口 和 用lambda表达式写函数式接口

在这里插入图片描述

上述为实现Runable的匿名类中的一个run方法

可以写成 Lanbda 表达式的条件

  • 该类只有一个方法(所有就不用方法名了,直接写参数和内部表达式) : ( ) -> 方法

在这里插入图片描述

使用(6种)

Runnable r2 = () -> System.out.println("我爱你.."); //  语法格式一: 无参 ,无返回
public void Test2(){
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("sdsd");
        System.out.println("------------------------");
    //调用格式二: Lambda 需要一个参数 ,但是没有返回值
    //--------------------------------------------------------
        Consumer<String> consumer1 = (String s) -> {
            System.out.println(s);
        };
    //--------------------------------------------------------
        consumer1.accept("SDASDSA");
    }
public void Test3(){
    
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    consumer.accept("sdsd");
    //调用格式三: Lambda 数据类型只有一个参数时可以省略 ,因为可以由编译器推出,称为"数据推理"
    //----------------------------------------------------------------
    Consumer<String> consumer1 = (s) -> {//省略数据类型
        System.out.println(s);
    };
    //----------------------------------------------------------------
    consumer1.accept("SDASDSA");
}
public void Test4(){
    
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    consumer.accept("sdsd");
   //调用格式四: Lambda 若只有一个参数,参数的小括号可以省略
   //----------------------------------------------------------------
    Consumer<String> consumer1 = s -> {
        System.out.println(s);
    };
   //----------------------------------------------------------------
    consumer1.accept("SDASDSA");
}

public void Test5(){
   
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    };
    System.out.println("------------------------------");
     //调用格式五:Lambda  需要两个或两个以上的参数,多条执行语句,并且可以有返回值
     //----------------------------------------------------------------
    Comparator<Integer> com2 =(o1 ,o2) -> {
        System.out.println(o1);
        System.out.println(o2);
        return o1.compareTo(o2);
    };
     //----------------------------------------------------------------
}
public void Test6(){
   
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    };
    System.out.println("------------------------------");
    //调用格式五:Lambda  只有一条语句时,return 和大括号都可以省略
    //----------------------------------------------------------------
    Comparator<Integer> com2 =(o1 ,o2) -> o1.compareTo(o2);
    //----------------------------------------------------------------
}

本质

lambda表达式的本质: 作为函数式接口的实现


方法引用/构造器引用

什么是方法引用

图片内容为核心思想,看不懂继续往下看

在这里插入图片描述

简单来说就是 : 和所需要的lambda表达式:功能,参数类型,返回类型一样的方法已经有其他类写过了
,我就没必要重新写(有点方法可能很复杂,重写成本高),那么我就直接引用过来用就好了

什么时候能用方法引用

  • 引用方法比较复杂的使用用
  • 注意能够引用的方法必须和所需方法参数返回类型完全一致才能用
  • 当然有的参数类型是泛型(就由例如 Consumer consumer1 = out :: println; 的String指定)

在这里插入图片描述

在这里插入图片描述

案例: 引用java的System.out.println演示

方法引用的三种方法

方法一: 对象 :: 非静态方法

//lambda写法
Consumer<String> consumer = str -> System.out.println(str);
consumer.accept("北京");
//引用写法 :先写对象或new对象  , 再用对象名引用非静态方法  
PrintStream out = System.out;
Consumer<String> consumer1 = out :: println;//println()是非静态方法
consumer1.accept("北京");

方法二:类名 :: 静态方法

System.out.println("----------传统----------");
Function<Double,Long> function = new Function<Double, Long>() {
    @Override
    public Long apply(Double d) {
        return Math.round(d);
    }
};
function.apply(2.0);

System.out.println("----------lambda表达式-----------");
Function<Double,Long> function1 = d -> Math.round(d);
function1.apply(2.0);

System.out.println("----------方法引用静态方法/非静态方法-----------");
Function<Double,Long> function2 = Math :: round;
System.out.println(function2.apply(2.0));

方式三: 类:: 实例方法 (基本很少能想到用这个,属于是能用就用,不用也无所谓)

比较难理解的是: 如图片 compare(t1 ,t2) 和 t1.compare(t2) 会认为是可以1对1匹配等价的,

在这里插入图片描述

下图

test( t1,t2) 可以认为与 t1.equals(t2) 的t1 和 t2 匹配

(匹配指这样调用不会出现函数不一致的语法错误,仅此而已)

在这里插入图片描述

下图

Function的R对应getName()的返回值

T t 对应 getName() 的小括号的空值

一样可以匹配,不会语法错误

在这里插入图片描述

方式三还是不懂,那就能不用就不用吧,免得出问题

  • 想不到方法三,想方法二,方法一

  • 想不到三种方法,想lambda表达式

  • 想不到lambda表达式,就用传统写法


构造器引用

依旧是上面的传统方法,lambda表达式,引用方法

调用无参构造器

在这里插入图片描述


调用有一个参数构造器

在这里插入图片描述


调用多个参数构造器

在这里插入图片描述

引用写法是一样的,自动识别, 语法记住就好


数组引用

意会——>和方法引用类似

但是我觉得没必要多此一举23333333

在这里插入图片描述


Stream API

介绍

在这里插入图片描述

为什么要用StreamAPI

在这里插入图片描述

nosql不能直接sql语法进行数据库操作 ,就需要通过java层面写增删改查函数

比如mysql数据库可以通过sql语法对表进行过滤挑选( 如 select * from table1 where age >10;
返回table1 中年龄大于10的数据) ,

但是有的数据库不支持sql语法,需要在java层面对数据进行过滤,Stream就类似于用java的API实现sql语法的功能

在这里插入图片描述

在这里插入图片描述

只有执行终止操作才能生效(类似于sql语法的runback回滚)

终止操作是指中间对数据本身进行过滤的操作之后的所有操作( 如过滤完之后forEach()方法就是终止的方法之一)


创建Stream方法

方法一:通过集合

在这里插入图片描述

演示案例:

准备如下list数据进行演示

在这里插入图片描述

可自定义获取一些数据,如上方数据加入自定义的获取一个下方的employee的集合list

  • 通过该employee集合对象调用Stream(): 可获取顺序流(能按加入的顺序取出)
  • 通过该employee集合对象调用parallelStream():可获取并行流(可能有多个流同时取出,不一定按顺序)

在这里插入图片描述


方法二:通过数组

在这里插入图片描述

演示案例

在这里插入图片描述


方式三: 通过Stream的of()

在这里插入图片描述

演示案例

在这里插入图片描述


方式四:创建无限流(用得较少)

在这里插入图片描述


迭代(了解即可)

将返回结果作为新的输入参数,无限制循环(除非设限制如limit(10) : 限制10次)

可以用来造数据

在这里插入图片描述

以下打印效果

在这里插入图片描述

生成(了解即可)

可以用来造数据

如下生成十个随机数

在这里插入图片描述


Stream的中间操作

筛选与切片

只有如下四个方法是中间操作,其余都算终止操作

在这里插入图片描述

下方的list是一串员工数据employee包含Salary工资等信息

接收 :filter()

在这里插入图片描述

如下: 执行一次终止操作(如forEach())后必须重新用list.stream()生成一次Stream,否则报错

在这里插入图片描述


截断和跳过:limit() ,skip()

在这里插入图片描述

去重: distinct()

如下如果打印只会保留一个"刘强东";

在这里插入图片描述

映射

在这里插入图片描述

map(function)用法:

相当于将每个元素一个一个通过该function得到返回值,将返回值组成新序列

如果一个元素是stream()会将整个stream()放入

理解类比: list.add(1) ,

​ list.add(2),

​ list.add([3,4])

​ ——> [ 1 , 2 , [ 3 , 4 ] ]

在这里插入图片描述


flatMap(): 如果遇到stream会把它拆开

理解类比:

list.add(1);

list.add(2),

list.addAll([3,4])

——>[ 1 , 2, 3 ,4 ]

在这里插入图片描述

排序

在这里插入图片描述

演示案例:

在这里插入图片描述


Stream的终止操作

1.匹配和查找

在这里插入图片描述

在这里插入图片描述


allMatch(Predicate p) :是否全部满足p

在这里插入图片描述

anyMatch(Predicate p): 是否存在满足p

在这里插入图片描述


noneMatch(Predicate p): 是否没有满足p

在这里插入图片描述


firstFirst: 返回第一个

在这里插入图片描述


count(): 数数

在这里插入图片描述


max(Comparator p) : 按规则排序,拿最大

在这里插入图片描述

min(Comparator p): 按规则排序,拿最小

在这里插入图片描述


forEach(Comparator c): 迭代遍历 ,以下forEach属于一个stream 一个Colleate

在这里插入图片描述

在这里插入图片描述


2.规约

map进行映射,reduce进行规约——>举例(map求出每个工资元素,reduce进求sum)

在这里插入图片描述

T iden: 指设置的初始值

BinaryOperator : 指接收两个参数,返回一个结果的函数类型

如下案例初始值为10 ,再把1~10加起来 返回65给sum

在这里插入图片描述

求工资总和案例

在这里插入图片描述

不会写引用就用lambda表达式

在这里插入图片描述


3.收集

将流Stream转化为其他形式如:集合Set ,Map,list

在这里插入图片描述

方法: 注意红色几个用到较多,其他需要再查,可做了解

在这里插入图片描述

在这里插入图片描述


案例:查找工资>6000的收集为集合list

在这里插入图片描述


Optional类

为什么有Optional类

Optional可以通过检测空值的方式,避免空指针异常( 空指针异常指: 对象为空还用该对象调方法,从而报错)

在这里插入图片描述

Optional的方法

在这里插入图片描述

创建方法:

optional()

ofUullable()

在这里插入图片描述


没有optional时,我们只能向如下代码一样手动判断是否为空( 以下图片代码帮助理解手动判断,意思不要深究)

在这里插入图片描述


用optional代替手动判断if(null)的写法案例如下:

  • 构造成optional对象
  • 调用orElse(T)方法: 对象不空,就用该对象; 该对象为null,就用orElse(T)的备胎T
  • 若有返回对象,用get()将对象从optional获取

在这里插入图片描述


:比如通过optional获取原对象: 原对象不能为空 ,或用 判断方法isPresent()判断

在这里插入图片描述


其他对应调用方法

在这里插入图片描述

新的时间和日期API

属于java基础内容,学过java基础应该都知道, 就是 localdateTime() 处理时间那些方法,此处不多说

其他新特性

java8新特性比较特别特别的的就是以上

函数式接口,lambda表达式,Stream API 和 Optional类这些

其他的特性可能变成了java基础,不太明显

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值