JDK8新特性

前言

众所周知,JDK8作为常用的开发LTS(Long Term Support)版本,深受各大企业的爱好,但是里面的一些新特性,常被使用却直戳心胸,so,了解新特性早已是刻不容缓。

Lambda表达式

lambda表达式的要素

  • 必须是接口
  • 接口内必须只有一个抽象方法或者该接口可以被@FunctionalInterface注解修饰

1.创建一个接口

package com.ssy.demo;

public interface MyInter {

    void action();

}

2.创建一个接口实现类

package com.ssy.demo;


public class MyInterImpl implements MyInter{
    @Override
    public void action() {
        System.out.println("武术散打······不败神话");
    }
}

3.测试demo

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {

        MyInterImpl myInter = new MyInterImpl();
        myInter.action();

    }

}


运行结果

res

Lambda的格式是

(类型 参数, 类型 参数,······)-> {
	······
}

现在以上述的为例展示Lambda的表达式demo

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {

        MyInter inter = ()->{
            System.out.println("Lambda表达式写出来的");
        };
        
        inter.action();

    }

}


运行结果

res

注意:

  • 如果接口的方法没有参数,那么Lambda表达式的小括号内没有数据
  • 如果接口的方法有且仅有一个参数,那么小括号可以省略也可以不省略
  • 如果只有方法体只有一条语句,可以不需要大括号
  • 如果是有返回值的方法且方法体的语句仅有一条而且还是返回值,要么不写大括号不写return不写分号,要么写大括号写return写分号

说白了Lambda就是匿名函数,仅此而已。

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {

        Demo demo = name -> name + "真好吃";
        String res = demo.eat("提拉米苏");
        System.out.println(res);
    }

}

interface Demo{

    String eat(String name);
}

运行结果

res

函数式接口

供给型接口Supplier

特点:无参有返回值

源码

res

测试Demo

res

消费型接口Consumer

特点:有参无返回值

源码

res

测试Demo

res

Function<T, R>接口

特点:有参有返回值

源码

res

测试Demo

res

断言Predicate接口

特点:有参返回值为boolean类型

源码

res

测试Demo

res

接口强化

JDK8之前接口里面只有公有静态常量和公有抽象方法,JDK新增了默认方法和公共静态方法

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {
        Ssy.myWorld();
        System.out.println("----------------------");
        Demo demo = new Demo();
        demo.action();
        System.out.println("----------------------");
        Ssy ssy = new Demo();
        ssy.action();
    }
}

interface Ssy{

    default void action(){
        System.out.println("动作事件");
    }

    static void myWorld(){
        System.out.println("我的世界······");
    }
}

class Demo implements Ssy{

    @Override
    public void action() {
        System.out.println("按钮左键点击动作");
    }
}

运行结果

res

默认方法与静态方法的区别
1.默认方法可以被继承,通过new对象调用
2.静态方法不能被继承,通过接口类名.方法名调用

方法引用

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。

注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"

package com.ssy.demo;

import java.util.function.Consumer;

public class JDK8 {

    public static void main(String[] args) {
        Consumer<String> demo = System.out::println;
        demo.accept("Hello Java");
    }
}

运行结果

res

对象名引用成员方法

对象名::方法名

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {
        Demo demo = System.out::println;
        demo.say("大家好,初来乍到,多多指教");
    }
}

interface Demo{

    void say(String text);

}

运行结果

res

类名引用静态方法

类名::静态方法

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {
       Demo<Boolean, String> demo = String::valueOf;
        System.out.println(demo.out(false).length());
    }
}

interface Demo<T,R>{

     R out(T val);

}

运行结果

res

类名引用实例方法

类名::成员方法名

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {
       Demo<String, Boolean> demo = String::isEmpty;
        System.out.println(demo.out("123"));
    }
}

interface Demo<T,R>{

     R out(T val);

}

运行结果

res

引用构造方法

类名::new

package com.ssy.demo;

public class JDK8 {

    public static void main(String[] args) {
        Demo<String,Bird> demo = Bird::new;
        Bird bird = demo.out("我是一只小小鸟");
        System.out.println(bird);
    }
}

interface Demo<T,R>{

     R out(T val);

}

class Bird{

    private String name;

    public Bird(String name){
        this.name = name;
    }

    @Override
    public String toString() {
        return "Bird{ name: " + name + "}";
    }
}

运行结果

res

Stream流

在使用集合相关的操作中,比如过滤、匹配、遍历、排序等操作时总是需要循环来遍历所有元素,从而来得到需要的结果,但我们更关注的是实现需求的逻辑,而不是如何循环。使用流操作更方便高效,流不是数据结构,只是在元数据集上定义了一组操作。

小demo1

package com.ssy.demo;

import java.util.ArrayList;
import java.util.List;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("250");
        list.add("110");
        list.add("100");
        list.add("120");
        list.add("99");

        list.stream().filter(s -> Integer.parseInt(s)>120).forEach(System.out::println);
    }
}

运行结果

res

小demo2

package com.ssy.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JDK8 {

    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        map.put("001",100);
        map.put("002",99);
        map.put("003",101);
        map.put("004",98);
        map.put("001",102);

        map.values().stream().forEach(System.out::println);
    }
}

运行结果

res

小demo3

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("张三", "李四", "王五").collect(Collectors.toList());
        long count = list.stream().count();
        System.out.println(count);
    }
}

运行结果

res

小demo4

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("张三", "李四", "王五","赵六","孙七","周八","刘九","孙十").collect(Collectors.toList());
        list.stream().limit(2).forEach(System.out::println);
    }
}

运行结果

res

小demo5

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("张三", "李四", "王五","赵六","孙七","周八","刘九","孙十").collect(Collectors.toList());
        list.stream().skip(7).forEach(System.out::println);
    }
}

运行结果

res

小demo6

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("1", "2", "3","4","5","6","7","8").collect(Collectors.toList());
        list.stream().map(s->Integer.parseInt(s)>5).forEach(System.out::println);
    }
}

运行结果

res

小demo7

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("1111","2","33","444").collect(Collectors.toList());
        list.stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);
    }
}

运行结果

res

小demo8

package com.ssy.demo;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        List<String> list = Stream.of("111","2","2","111").collect(Collectors.toList());
        list.stream().distinct().forEach(System.out::println);
    }
}

运行结果

res

小demo9

package com.ssy.demo;

import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JDK8 {

    public static void main(String[] args) {
        ArrayList<Integer> arr = Stream.of(1, 2, 3, 4, 5, 6).collect(Collectors.toCollection(ArrayList::new));
        arr.stream().forEach(System.out::println);
    }
}

运行结果

res

stream链式调用的时候注意终结点
res

时间和日期

JDK8之前用的是线程不安全的Calendar.getInstance对日期进行操作,JDK8推出了新的时间日期的API,且线程是安全的。

日期

package com.ssy.demo;

import java.time.LocalDate;

public class JDK8 {

    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println("当前的日期是" + date);
        System.out.println("年:" + date.getYear());
        System.out.println("英文月:" + date.getMonth().toString().toLowerCase());
        System.out.println("月份值:" + date.getMonthValue());
        System.out.println("日:" + date.getDayOfMonth());
        LocalDate year = date.withYear(2000);
        System.out.println("修改之后的日期:" + year);
    }
}

运行结果

res

时间

package com.ssy.demo;

import java.time.LocalTime;

public class JDK8 {

    public static void main(String[] args) {
        LocalTime now = LocalTime.now();
        System.out.println(now);
        System.out.println(now.getHour());
        System.out.println(now.withHour(12));
    }
}

运行结果

res

日期时间

package com.ssy.demo;

import java.time.LocalDateTime;

public class JDK8 {

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        System.out.println(now.getYear());
        System.out.println(now.withMonth(2));
    }
}

运行结果

res

格式化

package com.ssy.demo;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class JDK8 {

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String s = now.format(formatter);
        System.out.println(s);
    }
}

运行结果

res

日期时间差

package com.ssy.demo;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;

public class JDK8 {

    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        LocalDate dateEnd = LocalDate.of(2030, 10, 10);
        Period dpe = Period.between(date, dateEnd);
        System.out.println(dpe.getYears());

        LocalTime time = LocalTime.now();
        LocalTime timeEnd = LocalTime.of(22, 22, 22);
        Duration tdu = Duration.between(time, timeEnd);
        System.out.println(tdu.toHours());
    }
}

运行结果

res

时间校正器

package com.ssy.demo;

import java.time.*;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class JDK8 {

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();

        TemporalAdjuster t = temporal -> {
            LocalDateTime dateTime = (LocalDateTime) temporal;
            return dateTime.plusMonths(1).withDayOfMonth(1);
        };
        System.out.println(now.with(t));

        System.out.println(now.with(TemporalAdjusters.firstDayOfNextYear()));
    }
}

运行结果

res

重复注解和类型注解

重复注解

JDK5出现了注解,但是不能在一个类、方法、字段上出现重复的注解,JDK8很好的解决了这个问题。
前提:需要一个注解容器和一个注解内容,注解内容上的@Repeatable用来指定重复注解的容器,getAnnotationByType获取定义的所有的重复的注解。

package com.ssy.demo;

import java.lang.annotation.*;

public class JDK8 {

    public static void main(String[] args) {
        Demo[] demos = Test.class.getAnnotationsByType(Demo.class);
        for (Demo demo : demos) {
            System.out.println(demo.value());
        }
    }
}

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno{
    Demo[] value() default {};
}

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyAnno.class)
@interface Demo{
    String value() default "";
}

@Demo("张三")
@Demo("李浩")
class Test{

}

运行结果

res

类型注解

JDK8在@Target中新出现了TYPE_USE(表示注解可以写在任何用到类型的地方)、TYPE_PARAMETER(表示该注解能写在类型参数的声明语句中,也就是泛型)两个枚举变量

res

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值