Java8新特性总结

Java8新特性总结

刚毕业入职新公司,发现公司项目代码主要是以Java8为基础,其中用到了一些之前版本没有的特性,特此总结一下日常开发中使用比较多的Java8的新特性。
- lambda 表达式
- Stream 接口
- Date/Time API
- *接口的默认方法与静态方法
- Java虚拟机(JVM)的新特性


lambda 表达式

之前学过python,其语法就支持lambda表达式,通过lambda表达式,可以简化很多的语法。而Java8开始,Java也支持了lambda表达式。

示例1 使用lambda实现Runnable接口

//java8之前版本
new Thread(new Runnable() {
    @Override
    public void run() {
    System.out.println("Before Java8, too much code for too little to do");
    }
}).start();
//java8 lambda表达式实现
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();

之前版本采用匿名类实现Runnable接口,使用lambda表达式后如上所示,使代码简洁了很多。

示例2 使用lambda对列表进行迭代

对集合类中的元素经常进行遍历迭代操作,而使用lamdba语法能够使得迭代操作的语法更简单。

//java8以前对集合进行迭代
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
    System.out.println(feature);
}

示例3 Java 8中使用lambda表达式的Map和Reduce示例

//java8以后
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));

// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
features.forEach(System.out::println);
// 不使用lambda表达式为每个订单加上12%的税
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
for (Integer cost : costBeforeTax) {
    double price = cost + .12*cost;
    System.out.println(price);
}

// 使用lambda表达式
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);

Stream 接口

很多人对Stream的概念不是很理解,Java里对Stream的定义是“A sequence of elements supporting sequential and parallel aggregate operations.”可以看出,Stream是元素的集合,可以支持顺序和并行的操作。基于这一点,我们可以把Stream理解为一个高级迭代器。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。
以前我们利用集合完成排序,取值操作可能需要的代码

List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
 if(t.getType() == Transaction.GROCERY){
 groceryTransactions.add(t);
 }
}
Collections.sort(groceryTransactions, new Comparator(){
 public int compare(Transaction t1, Transaction t2){
 return t2.getValue().compareTo(t1.getValue());
 }
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
 transactionsIds.add(t.getId());
}

而通过Stream API

List<Integer> transactionsIds = transactions.parallelStream().
 filter(t -> t.getType() == Transaction.GROCERY).
 sorted(comparing(Transaction::getValue).reversed()).
 map(Transaction::getId).
 collect(toList());

它就像一个高级迭代器,可以在迭代的同时帮助我们完成我们需要的过滤排序的操作,极大地简化了我们的代码。

Date/Time API

让我们用例子来看一下新版API主要类的使用方法。第一个是Clock类,它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。

// Get the system clock as UTC offset 
final Clock clock = Clock.systemUTC();
System.out.println( clock.instant() );
System.out.println( clock.millis() );

控制台输出

2014-04-12T15:19:29.282Z
1397315969360

LocaleDate与LocalTime。LocaleDate只持有ISO-8601格式且无时区信息的日期部分。相应的,LocaleTime只持有ISO-8601格式且无时区信息的时间部分。LocaleDate与LocalTime都可以从Clock中得到。

// Get the local date and local time
final LocalDate date = LocalDate.now();
final LocalDate dateFromClock = LocalDate.now( clock );

System.out.println( date );
System.out.println( dateFromClock );

// Get the local date and local time
final LocalTime time = LocalTime.now();
final LocalTime timeFromClock = LocalTime.now( clock );

System.out.println( time );
System.out.println( timeFromClock );

控制台输出

2014-04-12
2014-04-12
11:25:54.568
15:25:54.568

LocaleDateTime把LocaleDate与LocaleTime的功能合并起来,它持有的是ISO-8601格式无时区信息的日期与时间。

// Get the local date/time
final LocalDateTime datetime = LocalDateTime.now();
final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );

System.out.println( datetime );
System.out.println( datetimeFromClock );

控制台输出

2014-04-12T11:37:52.309
2014-04-12T15:37:52.309

在我们日常开发过程中,经常要计算两个时间戳之间的时间,我们之前可能需要自己写逻辑计算,在java8中通过Duration类,我们可以快速得到两个时间戳之间的天数间隔。

// Get duration between two dates
final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );
final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );

final Duration duration = Duration.between( from, to );
System.out.println( "Duration in days: " + duration.toDays() );
System.out.println( "Duration in hours: " + duration.toHours() );

控制台输出

Duration in days: 365
Duration in hours: 8783

接口的默认方法与静态方法

java8之前,接口中的所有方法都必须是抽象方法,并且一个类实现接口时,也必须实现其中的所有方法,否则其必须为抽象类。java8中,新增了接口的默认方法和静态方法

 public interface MyInter {
     default void df(){    //声明一个接口的默认方法

         System.out.println("i'am default f");
         sf();        //调用本接口的类方法
     }     static void sf(){    //声明一个接口的类方法

         System.out.println("i'am static f");
     }
 }
public class Man implements MyInter{    //Man类实现MyInter接口
}
public class Test extends Man{

    public static void main(String[] args) {
        Man man=new Man();
        man.df();        //通过man对象调用MyInter接口的默认方法df()
    }

}

如上所示,默认方法可以通过实现类实例化的对象调用,而静态方法只能在本接口中调用或者在实现类中实现。

Java虚拟机(JVM)的新特性

PermGen空间被移除了,取而代之的是Metaspace(JEP122)。JVM选项-XX:PermSize与-XX:MaxPermSize分别被-XX:MetaSpaceSize与-XX:MaxMetaspaceSize所代替。

总结了一些常用的Java8的新特性,听说Java9也快要来了,果然coding这一行要不停的学习啊~

阅读更多
换一批

没有更多推荐了,返回首页