本文是 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 官方博客。