Java8新特性介绍

前言

由于博主在铜三铁四时期面试了一家**公司,然后对方面试官噼里啪啦的从数据结构到算法,从java源码到架构设计,足足面了一个小时。这里不得不恭维一下,该司面试官还是属于追求技术,有一定实力的程序猿。嘿嘿,但是到了博主反问业务的时候,他们说就是做一个数据对接,规则清洗,然后数据可视化的平台。这不是典型的面试造航母,工作拧螺丝。%*&%¥#!…(妈卖批)
好吧,不吐槽了,别人问的问题我确实不太会,现在来简单了解一下Java8的一些比较好用的特性吧,开干!!!!

主要知识点

由于Java8新特性比较多,我们只讲解一些比较实用的特性,其他的希望各位自己慢慢研究吧 ( * _ * )

  • default关键字
  • lamda表达式和函数式编程
  • stream流
  • 新的日期API
  • 重复注解
  • optional的使用

default关键字

在Java8之前,interface里面只允许有接口的定义,不允许进行接口的实现。但是自从default关键字的出现,interface里面也可以定义接口实现了,这样一来对于接口扩展带来了便利。然后接口实现类的实现方法里面都可以调用接口里面定义的default方法。代码如下:

接口定义:

public interface DefaultInteface {

    void complete();

    default Integer add(){
        return new Random().nextInt();
    }
}

接口实现类:

public class DefaultTest implements DefaultInteface{

    @Override
    public void complete() {
        this.add();
    }

    public void test(){
        add();
    }
}

lamda表达式和函数式接口

lamda表达式的出现简化了代码量,使代码更简洁,lamda表达式在集合遍历、线程定义、比较器里面用的比较多,具体代码如下:

  //线程定义
    public void test(){
        Runnable runnable = ()-> System.out.println("显示定义线程");
        new Thread(runnable).start();;
    }

    //集合遍历
    public void sort(){
        List<String> list = new ArrayList<>();
        list.forEach(s -> System.out.println(s));
    }

    //比较器
    public void add(){
        Comparator<Integer> comparable = (x, y)->y.compareTo(y);
        comparable.compare(1,2);
    }

Consumer是一个函数式编程接口; 顾名思义,Consumer的意思就是消费,即针对某个东西我们来使用它,因此它包含有一个有输入而无输出(无返回值)的accept接口方法;
除accept方法,它还包含有andThen这个方法

JDK源码定义如下:



default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };

 }

andThen这个方法是作用是:指定在调用当前Consumer后是否还要调用其它的Consumer;

public static void main(String[] args) {
        //定义第一个Consumer
        Consumer<Integer> consumer1 = (param) -> {System.out.println(param);};
        
        //定义第二个Consumer
        Consumer<Integer> consumer2 = (param) -> {System.out.println(param * param);};
        
        //consumer1可以连续的调用自己
        //consumer1.andThen(consumer1).andThen(consumer1).accept(3);
        //打印出 3 3 3
        
        //consumer1可以调用自己后调用consumer2
        consumer1.andThen(consumer1).andThen(consumer2).accept(3);
        //打印出3 3 9
    }

stream流

stream流是一种相对于迭代器代码更简洁,效率更高的工具。它可以对一个集合进行遍历、排序、分组、聚合等操作。下面我们将演示使用迭代器和stream之间的性能差异,以100000个数据的List集合为例:

public class StreamClass {

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            nameList.add("");
        }

        long start = System.currentTimeMillis();
        for (String s : nameList) {
            System.out.print(s);
        }
        long end = System.currentTimeMillis();
        System.out.println();
        System.out.println("迭代器时间:" + (end - start));

        start = System.currentTimeMillis();
        nameList.stream().forEach(name ->
                System.out.print(""));
        end = System.currentTimeMillis();
        System.out.println();
        System.out.println("stream流时间:" + (end - start));
    }
}

我们可以看到在10w级,100w级数据,stream流的性能远远强于迭代器,

10w级数据,迭代器10ms,stream流5ms
在这里插入图片描述
100w级数据,迭代器62ms,stream流42ms
在这里插入图片描述

新的日期API

Java8之前我们用的日期时间api是Date,DateTime,Calendar,SimpleDateFormat这些。Java8的时候提供了LocalDate,LocalTime,LocalDateTime,Duration,Period这些API。其中:

  • LocalDate获取日期
  • LocalTime获取时间
  • LocalDateTime同时获取日期和时间
  • Duration计算两个时间之间的差值
  • Period计算两个日期之间的差值

代码示例如下:

public static void main(String[] args) {

        //获取当前日期
        System.out.println(LocalDate.now());

        //获取当前时间
        System.out.println(LocalTime.now());

        //获取当前日期时间
        System.out.println(LocalDateTime.now());

        //计算两个时间的时间差
        LocalTime localTime = LocalTime.of(1,2);
        LocalTime localTime2 = LocalTime.of(5,2);
        System.out.println(Duration.between(localTime,localTime2));

        //计算两个日期差
        LocalDate localDate = LocalDate.of(2022,1,1);
        LocalDate localDate2 = LocalDate.of(2022,5,12);
        System.out.println(Period.between(localDate,localDate2));
    }

注解

Java8新增类型注解和重复注解。

  • 重复注解:可以在一个类上或方法上重复多次使用的注解
    自定义可重复注解:使用@Repeatable元注解,参数为可重复注解的容器
 @Repeatable(MyAnnotations.class)
    @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        String value() default "java8";
    }

注解容器定义,注意:可重复注解的容器的Target和Retention必须要比可重复注解的范围大

@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotations {
        MyAnnotation[] value();
    }

使用:

public class TestAnnotation {

	@Test
	public void test() throws NoSuchMethodException, SecurityException {
		Class<TestAnnotation> clazz = TestAnnotation.class;
		Method method = clazz.getMethod("show");
		MyAnnotation[] annotationsByType = method.getAnnotationsByType(MyAnnotation.class);
		for (MyAnnotation myAnnotation : annotationsByType) {
			System.out.println(myAnnotation.value());
		}
	}

	@MyAnnotation("hello")
	@MyAnnotation("world")
	public void show() {
	}
}
  • 类型注解:在入参的地方可以使用自定义注解,只需要将自定义注解的目标类型标注为ElementType.PARAMETER
@Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String value() default "java8";
}
public void show(@MyAnnotation("str") String str) {
	System.out.println(str);
}

optional的使用

optional的方式是java提供的对于类之间调用链提供的辅助类,使用optional可以很好避免一些NullPointerException异常的出现,使用方式如下:

public class Person {
    private Man man;
    public Man getman(){
        return man;
    }
}

public class Man {

    private Son son;
    public Son getSon(){
        return son;
    }
}

public class Son {

    private int age;
    public int getAge(){
        return age;
    }
}

    	//正常获取年龄
        Person person = new Person();
        System.out.println(person.getman().getSon().getAge());

        //optional方式获取年龄
        Person person1 = new Person();
        System.out.println(Optional.ofNullable(person)
                .map(Person::getman)
                .map(Man::getSon)
                .map(Son::getAge)
                .orElse(null));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值