本文是 DZone 指南 Java 生态系统的专题文章。点击连接可阅读更多看法深入的文章、行业统计信息,系 OneAPM工程师编译整理。html
Optional
类型在处理 null 值时,能减小 NullPointerExceptions 的可能性,给开发者极大的灵活度。去年年初,Java8 粉墨登场,如今 Java7 便已行将就木。在明年末 Java9 推出以前,Java8 是 Oracle 惟一支持的版本。然而,许多公司都将稳定性放在第一位,因此都还在用 Java7,甚至 Java6。java
让咱们来了解一下 Java8 的一些特性,让你在说服团队升级 Java 版本时理由能更充分一些。express
能够取悦老板、知足业务或运营人员的一大卖点是:Java8 运行应用时速度更快。一般,升级至 Java8 的应用都能获得速度上的提高,即使没有作任何改变或调优。对于为了迎合特定 JVM 而作出调整的应用,这或许并不适用。但 Java8 性能更优的理由还有不少:api
常见数据结构的性能提高:对广受欢迎的 HashMap 进行的基准测试代表,它们在 Java8 中的性能更好。这种提高很是吸引人——你无需学习新的 Streams API 或 Lambda 语法,甚至不须要改变现有的代码,就能提高应用的性能。服务器
垃圾回收器提高:一般,Java 应用性能取决于垃圾回收的效率。的确,糟糕的垃圾回收会很大程度上影响应用性能。Java8 对垃圾回收作了不少改变,能有效提高性能并简化调优。最为人熟知的改变是 PermGen 的移除与 Metaspace 的引入。数据结构
Fork/Join 速度提高:fork/join 框架是在 Java7 中首次引入的,目的是简化使用 JVM 的并发程序。Java8 中投入了不少努力进一步提高该框架。如今,fork/join 在 Streams API 中用于并发操做。并发
此外,Java8 中还包含诸多改进以支持并发。Oracle 在 JDK 8 中总结了这些性能提高。oracle
Java 常常被人们诟病其样本代码太多。为此,Java8 新的 API 采用了更具功能性的方式,专一于实现什么而不是如何实现。框架
Java8 中的 Lambda 表达式不只是 Java 已有的匿名内部类—— Java8 推出以前传递行为的方法以外的语法糖衣。Lambda 表达式采用了 Java 7 的内部改变,所以运用起来至关流畅。想了解如何使用 Lambda 表达式简化代码,请继续阅读。ide
Lambda 表达式与 Streams 多是 Java8 最大的两个卖点,较少为人知的是 Java 如今容许开发者给现有类添加新的方法,而无需为了向后兼容性折中。这样,新的方法,结合 Lambda 表达式,能在很大程序上简化代码。好比,咱们经常须要判断 Map 中的某个成员是否已经存在,若是不存在则建立之。在 Java8 以前,你可能会这么作:
private final Map<CustomerId, Customer> customers = new HashMap<>(); public void incrementCustomerOrders(CustomerId customerId) { Customer customer = customers.get(customerId); if (customer == null) { customer = new Customer(customerId); customers.put(customerId, customer); } customer.incrementOrders(); }
操做“检查某个成员在 map 中是否存在,若不存在则添加之”是如此经常使用,Java 如今为 Map
添加了一个新方法 computeIfAbsent
来支持这个操做。该方法的第二个参数是一个 Lambda 表达式,该表达式定义了如何建立缺乏的成员。
public void incrementCustomerOrders(CustomerId customerId) { Customer customer = customers.computeIfAbsent(customerId, id -> new Customer(id)); customer.incrementOrders(); }
其实,Java8 还有一个新的特性,称为方法引用(method references),它能使咱们用更简洁的代码实现该功能:
public void incrementCustomerOrders(CustomerId customerId) { Customer customer = customers.computeIfAbsent(customerId, Customer::new); customer.incrementOrders(); }
Java8 为 Map
与 List
都添加了新方法。你能够了解一下这些新方法,看它们能节省多少行代码。
Streams API 为查询、操纵数据提供了更多灵活度。这是一个很强大的功能。阅读这些文章能对 Streams API 有更全面的了解。在大数据时代创建流畅的数据查询会很是有趣,并且也是经常使用的操做。好比,你有一列书,你但愿按照字母表顺序排列这些书的做者名,且不含重复。
public List<Author> getAllAuthorsAlphabetically(List<Book> books) { List<Author> authors = new ArrayList<>(); for (Book book : books) { Author author = book.getAuthor(); if (!authors.contains(author)) { authors.add(author); } } Collections.sort(authors, new Comparator<Author>() { public int compare(Author o1, Author o2) { return o1.getSurname().compareTo(o2.getSurname()); } }); return authors; }
在上面的代码中,咱们首先遍历这列书,若是书的做者从未在做者列表出现,则添加之。以后,咱们根据做者的姓氏按字母表顺序对这些做者排序。这种排序操做正是 Streams 擅长解决的领域:
public List<Author> getAllAuthorsAlphabetically(List<Book> books) { return books.Streams() .map(book -> book.getAuthor()) .distinct() .sorted((o1, o2) -> o1.getSurname().compareTo(o2.getSurname())) .collect(Collectors.toList()); }
上面的作法不只代码行更少,并且描述性更强——后来的开发者读到这段代码可以轻易理解:一、代码从书中获取做者姓名。二、只在乎从未出现过的做者。三、返回的列表按照做者姓氏排序。将 Streams API 与其余新特性——方法引用(method references)、比较器(Comparator)的新方法结合使用,能够获得更加简洁的版本:
public List<Author> getAllAuthorsAlphabetically(List<Book> books) { return books.Streams() .map(Book::getAuthor) .distinct() .sorted(Comparator.comparing(Author::getSurname)) .collect(Collectors.toList()); }
这里,排序方法按照做者姓氏排序,更加显而易见了。
此前咱们浅聊过更利于开箱即用的性能,除了前面提到过的特性,Java8 能更好地利用 CPU 内核。将前例中的 Streams 方法替换为 parallelStreams
,JVM 会将此运算分解为不一样的任务,使用 fork/join 将这些任务运行在多个核上。然而,并行化并非加速全部运算的魔法。并行化运算老是会带来更多工做——分解运算,整合结果,所以没法老是减小时间。可是,对适合并行化的例子,这么作仍是很有效率的。
Java8 的另外一个新特性是全新的 Optional
类型。该类型的含义是“我可能有值,也多是 null。“这样一来,API 就能够区分可能为 null 的返回值与绝对不会是 null 的返回值,从而最小化 NullPointerException
异常的发生概率。
Optional
最赞的用处是处理 null。例如,假设咱们要从一个列表中找一本特定的书,新建立的 findFirst()
方法会返回 Optional
类型的值,代表它没法确保是否找到特定的值。有了这个可选择的值,咱们接下来能够决定,若是是 null 值要如何处理。若是想要抛出一个自定义的异常,咱们可使用 orElseThrow
:
public Book findBookByTitle(List<Book> books, String title) { Optional<Book> foundBook = books.Streams() .filter(book -> book.getTitle().equals(title)) .findFirst(); return foundBook.orElseThrow(() -> new BookNotFoundException("Did not find book with title " + title)); }
或者,你能够返回其余书:
return foundBook.orElseGet(() -> getRecommendedAlternativeBook(title));
或者,返回 Optional
类型,这样,该方法的调用者能够本身决定书没找到时要怎么作。
Java8 做为 Java 语言的一次重大发布,包含语法上的更改、新的方法与数据类型,以及一些能默默提高应用性能的隐性改善。Oracle 已经再也不支持 Java 7,所以许多公司都被迫向 Java8 转移。好消息是,Java8 对业务、现有的应用以及指望提升生产力的开发者都好好多。原文地址
OneAPM for Java和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。想阅读更多技术文章,请访问 OneAPM 官方博客。