刚毕业入职新公司,发现公司项目代码主要是以Java8为基础,其中用到了一些之前版本没有的特性,特此总结一下日常开发中使用比较多的Java8的新特性。 - lambda 表达式 - Stream 接口 - Date/Time API - *接口的默认方法与静态方法 - Java虚拟机(JVM)的新特性
之前学过python,其语法就支持lambda表达式,通过lambda表达式,可以简化很多的语法。而Java8开始,Java也支持了lambda表达式。
之前版本采用匿名类实现Runnable接口,使用lambda表达式后如上所示,使代码简洁了很多。
对集合类中的元素经常进行遍历迭代操作,而使用lamdba语法能够使得迭代操作的语法更简单。
//java8以前对集合进行迭代 List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API"); for (String feature : features) { System.out.println(feature); }很多人对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());它就像一个高级迭代器,可以在迭代的同时帮助我们完成我们需要的过滤排序的操作,极大地简化了我们的代码。
让我们用例子来看一下新版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 1397315969360LocaleDate与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.568LocaleDateTime把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: 8783java8之前,接口中的所有方法都必须是抽象方法,并且一个类实现接口时,也必须实现其中的所有方法,否则其必须为抽象类。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() } }如上所示,默认方法可以通过实现类实例化的对象调用,而静态方法只能在本接口中调用或者在实现类中实现。
PermGen空间被移除了,取而代之的是Metaspace(JEP122)。JVM选项-XX:PermSize与-XX:MaxPermSize分别被-XX:MetaSpaceSize与-XX:MaxMetaspaceSize所代替。
总结了一些常用的Java8的新特性,听说Java9也快要来了,果然coding这一行要不停的学习啊~