语法层面

  • 扩展方法,现在,接口中可以有静态、默认方法。
  • Lambda 表达式,允许像对象一样传递匿名函数
  • Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用
  • Stream API,充分利用现代多核 CPU,可以写出很简洁的代码

1、default关键字

  在java里面,我们通常都是认为接口里面是只能有抽象方法,不能有任何方法的实现的,那么在jdk1.8里面打破了这个规定,引入了新的关键字default,通过使用default修饰方法,可以让我们在接口里面定义具体的方法实现,如下。

复制代码
public interface NewCharacter {
    
    public void test1();
    
    public default void test2(){
        System.out.println("我是新特性1");
    }

}
复制代码

  那这么定义一个方法的作用是什么呢?为什么不在接口的实现类里面再去实现方法呢?

  其实这么定义一个方法的主要意义是定义一个默认方法,也就是说这个接口的实现类实现了这个接口之后,不用管这个default修饰的方法,也可以直接调用,如下。

复制代码
public class NewCharacterImpl implements NewCharacter{

    @Override
    public void test1() {
        
    }
    
    public static void main(String[] args) {
        NewCharacter nca = new NewCharacterImpl();
        nca.test2();
    }

}
复制代码

 

  所以说这个default方法是所有的实现类都不需要去实现的就可以直接调用,那么比如说jdk的集合List里面增加了一个sort方法,那么如果定义为一个抽象方法,其所有的实现类如arrayList,LinkedList等都需要对其添加实现,那么现在用default定义一个默认的方法之后,其实现类可以直接使用这个方法了,这样不管是开发还是维护项目,都会大大简化代码量。

假如我们有一个已经投入使用接口需要拓展一个新的方法,在JDK8以前,如果为一个使用的接口增加一个新方法,则我们必须在所有实现类中添加该方法的实现,否则编译会出现异常。如果实现类数量少并且我们有权限修改,可能会工作量相对较少。如果实现类比较多或者我们没有权限修改实现类源代码,这样可能就比较麻烦。而默认方法则解决了这个问题,它提供了一个实现,当没有显示提供其他实现时就采用这个实现。这样新添加的方法将不会破坏现有代码。

2、Lambda 表达式(例如: (x, y) -> { return x + y; } ;λ表达式有三部分组成:一个括号内用逗号非分隔的参数列表,一个箭头(->),方法体(可以是一个表达式或语句块)。) 

  使用 Lambda 表达式可以使代码变的更加简洁紧凑。也可称为闭包,它是推动 Java 8 发布的最重要新特性。

  Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

 

复制代码
//这是常规的Collections的排序的写法,需要对接口方法重写
只需要给静态方法 Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法
        public void test1(){
        List<String> list =Arrays.asList("aaa","fsa","ser","eere");
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        for (String string : list) {
            System.out.println(string);
        }
    }
//,没必要使用上面传统的匿名对象的方式了
//这是带参数类型的Lambda的写法
public void testLamda1(){ List<String> list =Arrays.asList("aaa","fsa","ser","eere"); Collections.sort(list, (Comparator<? super String>) (String a,String b)->{ return b.compareTo(a); } ); for (String string : list) { System.out.println(string); } } //这是不带参数的lambda的写法 public void testLamda2(){ List<String> list =Arrays.asList("aaa","fsa","ser","eere"); Collections.sort(list, (a,b)->b.compareTo(a) //对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字 ); for (String string : list) { System.out.println(string); }

//都对
Collections.sort(list, (String a, String b) -> {
    return b.compareTo(a);
});

Collections.sort(list, (String a, String b) -> b.compareTo(a));

复制代码

  可以看到不带参数的写法一句话就搞定了排序的问题,所以引入lambda表达式的一个最直观的作用就是大大的简化了代码的开发,像其他一些编程语言Scala,Python等都是支持函数式的写法的。当然,不是所有的接口都可以通过这种方法来调用,只有函数式接口才行,jdk1.8里面定义了好多个函数式接口,我们也可以自己定义一个来调用,下面说一下什么是函数式接口。

 

 

4、Date Api更新

  1.8之前JDK自带的日期处理类非常不方便,java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。我们处理的时候经常是使用的第三方工具包,比如commons-lang包等。不过1.8出现之后这个改观了很多,比如日期时间的创建、比较、调整、格式化、时间间隔等。这些类都在java.time包下。比原来实用了很多。

复制代码

import java.time.LocalDate;

import java.time.LocalDateTime;

import java.time.LocalTime;

import java.time.Month;

public class Main {

   public static void main(String args[]){

      // 获取当前的日期时间

       LocalDateTime currentTime = LocalDateTime.now();

       System.out.println("当前时间: " + currentTime);

 

       LocalDate date1 = currentTime.toLocalDate();

       System.out.println("date1: " + date1);

       Month month = currentTime.getMonth();

       int day = currentTime.getDayOfMonth();

       int seconds = currentTime.getSecond();

       System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds);

       LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);

       System.out.println("date2: " + date2);

       // 12 december 2014

       LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);

       System.out.println("date3: " + date3);

       // 22 小时 15 分钟

       LocalTime date4 = LocalTime.of(22, 15);

       System.out.println("date4: " + date4);

       // 解析字符串

       LocalTime date5 = LocalTime.parse("20:15:30");

       System.out.println("date5: " + date5);

   }

}

复制代码

  结果:

复制代码
  1. 当前时间: 2018-05-27T14:25:48.347
  2. date1: 2018-05-27
  3. 月: MAY, 日: 27, 秒: 48
  4. date2: 2012-05-10T14:25:48.347
  5. date3: 2014-12-12
  6. date4: 22:15
  7. date5: 20:15:30
复制代码

DateTimeFormatter

 

   以前日期格式化一般用SimpleDateFormat类,但是不怎么好用,现在1.8引入了DateTimeFormatter类,默认定义了很多常量格式(ISO打头的),在使用的时候一般配合LocalDate/LocalTime/LocalDateTime使用,比如想把当前日期格式化成yyyy-MM-dd hh:mm:ss的形式:

 

LocalDateTime dt = LocalDateTime.now();  
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");         
System.out.println(dtf.format(dt));

 

DateTimeFormatter是不可变的,所以它是线程安全的

 

4、流

  Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。

也可看:https://blog.csdn.net/agzhchren/article/details/53715427

 

 

数据结构层面

1、hashmap 

①,从数组+链表的存储结构  转变为 数组+链表+红黑树的存储结构

②hashmap优化了重新计算hash的过程。

这个特性主要利用了每次扩增原长的一倍