Java8新特性总结

来源:互联网 发布:cps推广系统源码 编辑:程序博客网 时间:2024/06/05 00:40

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.282Z1397315969360

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

// Get the local date and local timefinal LocalDate date = LocalDate.now();final LocalDate dateFromClock = LocalDate.now( clock );System.out.println( date );System.out.println( dateFromClock );// Get the local date and local timefinal LocalTime time = LocalTime.now();final LocalTime timeFromClock = LocalTime.now( clock );System.out.println( time );System.out.println( timeFromClock );

控制台输出

2014-04-122014-04-1211:25:54.56815:25:54.568

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

// Get the local date/timefinal LocalDateTime datetime = LocalDateTime.now();final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );System.out.println( datetime );System.out.println( datetimeFromClock );

控制台输出

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

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

// Get duration between two datesfinal 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: 365Duration 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这一行要不停的学习啊~

原创粉丝点击