Java8新特性

轉自:http://www.oschina.NET/translate/everything-about-Java-8html

建議去看原文,此處轉載只是爲了記錄。java

這篇文章是對Java 8中即將到來的改進作一個面向開發者的綜合性的總結,JDK的這一特性將會在2013年9月份發佈。linux

在寫這篇文章的時候,java 8的開發工做仍然在緊張有序的進行中,語言特新和API仍然有可能改變,我會盡我最大的努力保持這份文檔跟獲得Java 8的改動。git

Java 8的預覽版,也就是 「Project Lambda」,如今能夠從java.net下載到。程序員

我使用了IntelliJ的預覽版作個人IDE,在我看來他是目前支持java 8特性最好的一個IDE,你能夠從這裏下載到.算法

因爲我沒有找到Oracle發佈的Java 8的官方文檔,因此目前Java 8的文檔還只有本地版本,等oracle公開文檔的時候,我將會從新連接到官方文檔。sql

JeromeCui
JeromeCui
翻譯於 3年前

2人頂api

 翻譯的不錯哦!數組

接口改善

如今接口裏已經徹底能夠定義靜態方法了. 舉一個比較廣泛的例子就是在java類庫中, 對於一些接口如Foo, 都會有一個有靜態方法的工具類Foos 來生成或者配合Foo對象實例來使用. 既然靜態方法能夠存在於接口當中, 那麼大多數狀況下 Foos工具類徹底可使用接口中的公共方法來代理 (或者將Foos置成package-private).數據結構

除此以外更重要的就是, Java 8中接口能夠定義默認的方法了.舉個例子,一個for-each循環的方法就能夠加入到java.lang.Iterable中:

?
1
2
3
4
5
public default  void  forEach(Consumer<?  super T> action) {
     Objects.requireNonNull(action);  for (T t :  this ) {
         action.accept(t);
     }
}

在過去,java類庫的接口中添加方法基本上是不可能的. 在接口中添加方法意味着破壞了實現了這個接口的代碼. 可是如今, 只要可以提供一個正確明智的默認的方法的實現, java類庫的維護者就能夠在接口中添加方法.

Java 8中, 大量的默認方法已經被添加到核心的JDK接口中了. 稍候我會詳細介紹它們.

叫我蝴蝶吧
叫我蝴蝶吧
翻譯於 3年前

2人頂

 翻譯的不錯哦!

爲何不能用默認方法來重載equals,hashCode和toString?

接口不能提供對Object類的任何方法的默認實現。特別是,這意味着從接口裏不能提供對equals,hashCode或toString的默認實現。

這剛看起來挺奇怪的,但考慮到一些接口其實是在文檔裏定義他們的equals行爲的。List接口就是一個例子了。所以,爲何不容許這樣呢?

Brian Goetz在這個問題上的冗長的回覆裏給出了4個緣由。我這裏只說其中一個,由於那個已經足夠說服我了:

它會變得更困難來推導何時該調用默認的方法。如今它變得很簡單了:若是一個類實現了一個方法,那老是優先於默認的實現的。一旦全部接口的實例都是Object的子類,全部接口實例都已經有對equals/hashCode/toString的非默認實現。所以,一個在接口上這些的默認版本都是沒用的,它也不會被編譯。

要看更多的話,看下由Brian Goetz寫的解釋: 對「容許默認方法來重載Object的方法」的回覆

excepiton
excepiton
翻譯於 3年前

3人頂

 翻譯的不錯哦!

函數式接口

Java 8 引入的一個核心概念是函數式接口。若是一個接口定義個惟一一個抽象方法,那麼這個接口就成爲函數式接口。好比,java.lang.Runnable就是一個函數式接口,由於它只頂一個一個抽象方法:

?
1
public abstract  void  run();
留意到「abstract」修飾詞在這裏是隱含的,由於這個方法缺乏方法體。爲了表示一個函數式接口,並不是想這段代碼同樣必定須要「abstract」關鍵字。

默認方法不是abstract的,因此一個函數式接口裏能夠定義任意多的默認方法,這取決於你。

同時,引入了一個新的Annotation:@FunctionalInterface。能夠把他它放在一個接口前,表示這個接口是一個函數式接口。加上它的接口不會被編譯,除非你設法把它變成一個函數式接口。它有點像@Override,都是聲明瞭一種使用意圖,避免你把它用錯。

JoeyBlue
JoeyBlue
翻譯於 3年前

6人頂

 翻譯的不錯哦!

Lambdas

一個函數式接口很是有價值的屬性就是他們可以用lambdas來實例化。這裏有一些lambdas的例子:

左邊是指定類型的逗號分割的輸入列表,右邊是帶有return的代碼塊:

?
1
( int x,  int y) -> {  return x + y; }

左邊是推導類型的逗號分割的輸入列表,右邊是返回值:

?
1
(x, y) -> x + y

左邊是推導類型的單一參數,右邊是一個返回值:

?
1
x -> x * x

左邊沒有輸入 (官方名稱: "burger arrow"),在右邊返回一個值:

?
1
() -> x

左邊是推導類型的單一參數,右邊是沒返回值的代碼塊(返回void):

?
1
x -> { System.out.println(x); }

靜態方法引用:

?
1
String::valueOf

非靜態方法引用:

?
1
Object::toString

繼承的函數引用:

?
1
x::toString

構造函數引用:

?
1
ArrayList:: new

你能夠想出一些函數引用格式做爲其餘lambda格式的簡寫。

excepiton
excepiton
翻譯於 3年前

3人頂

 翻譯的不錯哦!

方法引用  等價的lambda表達式
String::valueOf
x -> String.valueOf(x)
Object::toString
x -> x.toString()
x::toString
() -> x.toString()
ArrayList::new
() -> new ArrayList<>()

固然,在Java裏方法能被重載。類能夠有多個同名但不一樣參數的方法。這一樣對構造方法有效。ArrayList::new可以指向它的3個構造方法中任何一個。決定使用哪一個方法是根據在使用的函數式接口。

一個lambda和給定的函數式接口在「外型」匹配的時候兼容。經過「外型」,我指向輸入、輸出的類型和聲明檢查異常。

給出兩個具體有效的例子:

?
1
2
Comparator<String> c = (a, b) -> Integer.compare(a.length(),
                                                  b.length());

一個Comparator<String>的compare方法須要輸入兩個闡述,而後返回一個int。這和lambda右側的一致,所以這個任務是有效的。

?
1
Runnable r = () -> { System.out.println( "Running!" ); }

一個Runnable的run方法不須要參數也不會返回值。這和lambda右側一致,因此任務有效。

在抽象方法的簽名裏的受檢查異常(若是存在)也很重要。若是函數式接口在它的簽名裏聲明瞭異常,lambda只能拋出受檢查異常。

excepiton
excepiton
翻譯於 3年前

3人頂

 翻譯的不錯哦!

捕獲和非捕獲的Lambda表達式

當Lambda表達式訪問一個定義在Lambda表達式體外的非靜態變量或者對象時,這個Lambda表達式稱爲「捕獲的」。好比,下面這個lambda表達式捕捉了變量x:

?
1
int x =  5 return y -> x + y;
爲了保證這個lambda表達式聲明是正確的,被它捕獲的變量必須是「有效final」的。因此要麼它們須要用final修飾符號標記,要麼保證它們在賦值後不能被改變。

Lambda表達式是不是捕獲的和性能悄然相關。一個非不捕獲的lambda一般比捕獲的更高效,雖然這一點沒有書面的規範說明(據我所知),並且也不能爲了程序的正確性期望它作什麼,非捕獲的lambda只須要計算一次. 而後每次使用到它都會返回一個惟一的實例。而捕獲的lambda表達式每次使用時都須要從新計算一次,並且從目前實現來看,它很像實例化一個匿名內部類的實例。


JoeyBlue
JoeyBlue
翻譯於 3年前

3人頂

 翻譯的不錯哦!

lambdas不作的事

你應該記住,有一些lambdas不提供的特性。爲了Java 8它們被考慮到了,可是沒有被包括進去,因爲簡化以及時間限制的緣由。

Non-final* 變量捕獲 - 若是一個變量被賦予新的數值,它將不能被用於lambda之中。"final"關鍵字不是必需的,但變量必須是「有效final」的(前面討論過)。這個代碼不會被編譯:

?
1
2
3
4
int count =  0 ;
List<String> strings = Arrays.asList( "a" "b" "c" );
strings.forEach(s -> {
     count++;  // error: can't modify the value of count });

例外的透明度 - 若是一個已檢測的例外可能從lambda內部拋出,功能性的接口也必須聲明已檢測例外能夠被拋出。這種例外不會散佈到其包含的方法。這個代碼不會被編譯:

?
1
2
3
void appendAll(Iterable<String> values, Appendable out)  throws IOException {  // doesn't help with the error values.forEach(s -> {
         out.append(s);  // error: can't throw IOException here // Consumer.accept(T) doesn't allow it });
}

有繞過這個的辦法,你能定義本身的功能性接口,擴展Consumer的同時經過像RuntimeException之類拋出 IOException。我試圖用代碼寫出來,但發現它使人困惑是否值得。

控制流程 (break, early return) -在上面的 forEach例子中,傳統的繼續方式有可能經過在lambda以內放置 "return;"來實現。可是,沒有辦法中斷循環或者從lambda中經過包含方法的結果返回一個數值。例如:

?
1
2
3
4
5
final String secret =  "foo" boolean containsSecret(Iterable<String> values) {
     values.forEach(s -> {  if (secret.equals(s)) {
             ???  // want to end the loop and return true, but can't }
     });
}

進一步閱讀關於這些問題的資料,看看這篇Brian Goetz寫的說明:在 Block<T>中響應「已驗證例外」

super0555
super0555
翻譯於 3年前

3人頂

 翻譯的不錯哦!

其它翻譯版本(1)

爲何抽象類不能經過利用lambda實例化

抽象類,哪怕只聲明瞭一個抽象方法,也不能使用lambda來實例化。

下面有兩個類 Ordering 和 CacheLoader的例子,都帶有一個抽象方法,摘自於Guava 庫。那豈不是很高興可以聲明它們的實例,像這樣使用lambda表達式?

Ordering<String> order = (a, b) -> ...;

?
1
CacheLoader<String, String> loader = (key) -> ...;

這樣作引起的最多見的爭論就是會增長閱讀lambda的難度。以這種方式實例化一段抽象類將致使隱藏代碼的執行:抽象類的構造方法。

另外一個緣由是,它拋出了lambda表達式可能的優化。在將來,它多是這種狀況,lambda表達式都不會計算到對象實例。聽任用戶用lambda來聲明抽象類將妨礙像這樣的優化。

外,有一個簡單地解決方法。事實上,上述兩個摘自Guava 庫的實例類已經證實了這種方法。增長工廠方法將lambda轉換成實例。

?
1
2
Ordering<String> order = Ordering.from((a, b) -> ...);
CacheLoader<String, String> loader = CacheLoader.from((key) -> ...);

要深刻閱讀,請參看由 Brian Goetz所作的說明: response to "Allow lambdas to implement abstract classes"

等PM
等PM
翻譯於 3年前

1人頂

 翻譯的不錯哦!

java.util.function

包概要:java.util.function

做爲Comparator 和Runnable早期的證實,在JDK中已經定義的接口恰巧做爲函數接口而與lambdas表達式兼容。一樣方式能夠在你本身的代碼中定義任何函數接口或第三方庫。

但有特定形式的函數接口,且普遍的,通用的,在以前的JD卡中並不存在。大量的接口被添加到新的java.util.function 包中。下面是其中的一些:

  • Function<T, R> -T做爲輸入,返回的R做爲輸出
  • Predicate<T> -T做爲輸入,返回的boolean值做爲輸出
  • Consumer<T> - T做爲輸入,執行某種動做但沒有返回值
  • Supplier<T> - 沒有任何輸入,返回T
  • BinaryOperator<T> -兩個T做爲輸入,返回一個T做爲輸出,對於「reduce」操做頗有用

這些最原始的特徵一樣存在。他們以int,long和double的方式提供。例如:

  • IntConsumer -以int做爲輸入,執行某種動做,沒有返回值

這裏存在性能上的一些緣由,主要釋在輸入或輸出的時候避免裝箱和拆箱操做。

等PM
等PM
翻譯於 3年前

1人頂

 翻譯的不錯哦!

java.util.stream

包彙總: java.util.stream

新的java.util.stream包提供了「支持在流上的函數式風格的值操做」(引用javadoc)的工具。可能活動一個流的最多見方法是從一個collection獲取:

?
1
Stream<T> stream = collection.stream();

一個流就像一個地帶器。這些值「流過」(模擬水流)而後他們離開。一個流能夠只被遍歷一次,而後被丟棄。流也能夠無限使用。

流可以是 串行的 或者 並行的。 它們可使用其中一種方式開始,而後切換到另外的一種方式,使用stream.sequential()或stream.parallel()來達到這種切換。串行流在一個線程上連續操做。而並行流就可能一次出如今多個線程上。

因此,你想用一個流來幹什麼?這裏是在javadoc包裏給出的例子:

?
1
2
3
int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
                                   .mapToInt(b -> b.getWeight())
                                   .sum();

注意:上面的代碼使用了一個原始的流,以及一個只能用在原始流上的sum()方法。下面立刻就會有更多關於原始流的細節。

excepiton
excepiton
翻譯於 3年前

3人頂

 翻譯的不錯哦!

流提供了流暢的API,能夠進行數據轉換和對結果執行某些操做。流操做既能夠是「中間的」也能夠是「末端的」。

  • 中間的 -中間的操做保持流打開狀態,並容許後續的操做。上面例子中的filter和map方法就是中間的操做。這些操做的返回數據類型是流;它們返回當前的流以便串聯更多的操做。
  • 末端的 - 末端的操做必須是對流的最終操做。當一個末端操做被調用,流被「消耗」而且再也不可用。上面例子中的sum方法就是一個末端的操做。

一般,處理一個流涉及了這些步驟:

  1. 從某個源頭得到一個流。
  2. 執行一個或更多的中間的操做。
  3. 執行一個末端的操做。

可能你想在一個方法中執行全部那些步驟。那樣的話,你就要知道源頭和流的屬性,並且要能夠保證它被正確的使用。你可能不想接受任意的Stream<T>實例做爲你的方法的輸入,由於它們可能具備你難以處理的特性,好比並行的或無限的。

super0555
super0555
翻譯於 3年前

1人頂

 翻譯的不錯哦!

有幾個更普通的關於流操做的特性須要考慮:

  • 有狀態的 - 有狀態的操做給流增長了一些新的屬性,好比元素的惟一性,或者元素的最大數量,或者保證元素以排序的方式被處理。這些典型的要比無狀態的中間操做代價大。
  • 短路 - 短路操做潛在的容許對流的操做盡早中止,而不去檢查全部的元素。這是對無限流的一個特殊設計的屬性;若是對流的操做沒有短路,那麼代碼可能永遠也不會終止。

對每一個Sttream方法這裏有一些簡短的,通常的描述。查閱javadoc獲取更詳盡的解釋。下面給出了每一個操做的重載形式的連接。

中間的操做:

  • filter 1 - 排除全部與斷言不匹配的元素。
  • map 1 2 3 4 - 經過Function對元素執行一對一的轉換。
  • flatMap 1 2 3 4 5 - 經過FlatMapper將每一個元素轉變爲無或更多的元素。
  • peek 1 - 對每一個遇到的元素執行一些操做。主要對調試頗有用。
  • distinct 1 - 根據.equals行爲排除全部重複的元素。這是一個有狀態的操做。
  • sorted 1 2 - 確保流中的元素在後續的操做中,按照比較器(Comparator)決定的順序訪問。這是一個有狀態的操做。
  • limit 1 - 保證後續的操做所能看到的最大數量的元素。這是一個有狀態的短路的操做。
  • substream 1 2 - 確保後續的操做只能看到一個範圍的(根據index)元素。像不能用於流的String.substring同樣。也有兩種形式,一種有一個開始索引,一種有一個結束索引。兩者都是有狀態的操做,有一個結束索引的形式也是一個短路的操做。

末端的操做:

  • forEach 1 - 對流中的每一個元素執行一些操做。
  • toArray 1 2 - 將流中的元素傾倒入一個數組。
  • reduce 1 2 3 - 經過一個二進制操做將流中的元素合併到一塊兒。
  • collect 1 2 - 將流中的元素傾倒入某些容器,例如一個Collection或Map.
  • min 1 - 根據一個比較器找到流中元素的最小值。
  • max 1 -根據一個比較器找到流中元素的最大值。
  • count 1 - 計算流中元素的數量。
  • anyMatch 1 - 判斷流中是否至少有一個元素匹配斷言。這是一個短路的操做。
  • allMatch 1 - 判斷流中是否每個元素都匹配斷言。這是一個短路的操做。
  • noneMatch 1 - 判斷流中是否沒有一個元素匹配斷言。這是一個短路的操做。
  • findFirst 1 - 查找流中的第一個元素。這是一個短路的操做。
  • findAny 1 - 查找流中的任意元素,可能對某些流要比findFirst代價低。這是一個短路的操做。

如 javadocs中提到的 , 中間的操做是延遲的(lazy)。只有末端的操做會當即開始流中元素的處理。在那個時刻,無論包含了多少中間的操做,元素會在一個傳遞中處理(一般,但並不老是)。(有狀態的操做如sorted() 和distinct()可能須要對元素的二次傳送。) 

super0555
super0555
翻譯於 3年前

1人頂

 翻譯的不錯哦!

流試圖儘量作不多的工做。有一些細微優化,如當能夠斷定元素已經有序的時候,省略一個sorted()操做。在包含limit(x) 或 substream(x,y)的操做中,有些時候對一些不會決定結果的元素,流能夠避免執行中間的map操做。在這裏我不許備實現公平判斷;它經過許多細微的但卻很重要的方法表現得很聰明,並且它仍在進步。

回到並行流的概念,重要的是要意識到並行不是毫無代價的。從性能的立場它不是無代價的,你不能簡單的將順序流替換爲並行流,且不作進一步思考就指望獲得相同的結果。在你能(或者應該)並行化一個流之前,須要考慮不少特性,關於流、它的操做以及數據的目標方面。例如:訪問順序確實對我有影響嗎?個人函數是無狀態的嗎?個人流有足夠大,而且個人操做有足夠複雜,這些能使得並行化是值得的嗎?

super0555
super0555
翻譯於 3年前

1人頂

 翻譯的不錯哦!

有針對int,long和double的專業原始的Stream版本:

能夠在衆多函數中,經過專業原始的map和flatMap函數,在一個stream對象與一個原始stream對象之間來回轉換。給幾個虛設例子:

?
1
2
3
4
5
6
List<String> strings = Arrays.asList( "a" "b" "c" );
strings.stream()  //
Stream<String> .mapToInt(String::length)  // IntStream .longs() //
LongStream .mapToDouble(x -> x /  10.0 // DoubleStream .boxed() //
Stream<Double> .mapToLong(x -> 1L)  // LongStream .mapToObj(x -> "") //
Stream<String> ...

原始的stream也爲得到關於stream的基礎數據統計提供方法,那些stream是指做爲數據結構的。你能夠發現count, sum, min, max, 以及元素平均值所有是來自於一個終端的操做。

原始類型的剩餘部分沒有原始版本,由於這須要一個不可接受的JDK數量的膨脹。IntStream, LongStream, 和 DoubleStream被認爲很是有用應當被包含進去,其餘的數字型原始stream能夠由這三個經過擴展的原始轉換來表示。

super0555
super0555
翻譯於 3年前

2人頂

 翻譯的不錯哦!

在flatMap操做中使用的  FlatMapper 接口是具備一個抽象方法的功能性接口:
?
1
void flattenInto(T element, Consumer<U> sink);

在一個flatMap操做的上下文中,stream爲你提供element和 sink,而後你定義該用element 和 sink作什麼。element是指在stream中的當前元素,而sink表明當flatMap操做結束以後在stream中應該顯示些什麼。例如:

?
1
2
3
4
5
6
7
8
Set<Color> colors = ...;
List<Person> people = ...;
Stream<Color> stream = people.stream().flatMap(
     (Person person, Consumer<Color> sink) -> {  // Map each person to the colors they like. for (Color color : colors) { if (person.likesColor(color)) {
                 sink.accept(color);
             }
         }
     });

注意上面lambda中的參數類型是指定的。在大多數其它上下文中,你能夠不須要指定類型,但這裏因爲FlatMapper的天然特性,編譯器須要你幫助斷定類型。若是你在使用flatMap又迷惑於它爲何不編譯,多是由於你沒有指定類型。

最使人感到困惑,複雜並且有用的終端stream操做之一是collect。它引入了一個稱爲Collector的新的非功能性接口。這個接口有些難理解,但幸運的是有一個Collectors工具類可用來產生全部類型的有用的Collectors。例如:

?
1
2
3
4
List<String> strings = values.stream()
                              .filter(...)
                              .map(...)
                              .collect(Collectors.toList());

若是你想將你的stream元素放進一個Collection,Map或String,那麼Collectors可能具備你須要的。在javadoc中瀏覽那個類絕對是值得的。

super0555
super0555
翻譯於 3年前

2人頂

 翻譯的不錯哦!

泛型接口改進

建議摘要:JEP 101: 通用化目標-Type 接口

這是一個之前不能作到的,對編譯器斷定泛型能力的努力改進。在之前版本的Java中有許多情形編譯器不能給某個方法計算出泛型,當方法處於嵌套的或串聯方法調用這樣的上下文的時候,即便有時候對程序員來講它看起來「很明顯」。那些狀況須要程序員明確的指定一個「類型見證」(type witness)。它是一種通用的特性,但吃驚的是不多有Java程序員知道(我這麼說是基於私下的交流而且閱讀了一些StackOverflow的問題)。它看起來像這樣:

?
1
2
// In Java 7: foo(Utility.<Type>bar());
Utility.<Type>foo().bar();

若是沒有類型見證,編譯器可能會將<Object>替代爲泛型,並且若是須要的是一個更具體的類型,代碼將編譯失敗。

Java 8 極大的改進了這個情況。在更多的案例中,它能夠基於上下文計算出更多的特定的泛型類型。
?
1
2
// In Java 8: foo(Utility.bar());
Utility.foo().bar();

這項工做仍在發展中,因此我不肯定建議中列出的例子有多少能真正包含進Java 8。但願是它們所有。

super0555
super0555
翻譯於 3年前

1人頂

 翻譯的不錯哦!

其它翻譯版本(1)

java.time

包概要: java.time

在Java8中新的 date/timeAPI存在於 java.time包中。若是你熟悉Joda Time,它將很容易掌握。事實上,我認爲如此好的設計,以致於從未據說過 Joda Time的人也能很容易的掌握。

幾乎在API中的任何東西都是永恆的,包括值類型和格式化 。對於Date域或者處理或處理本地線程日期格式化沒必要太過擔憂。

與傳統的date/timeAPI的交叉是最小的。有一個清晰的分段:


新API對於像月份和每週的天數,喜歡枚舉類型更賽過整形常量。

那麼,那是什麼呢?包級別的javadocs 對額外類型的作出了很是好的闡述。我將對一些值得注意的部分作一些簡短的綱要。

很是有用的值類型:

其餘有用的類型:

  • DateTimeFormatter - 將日期類型轉換成字符串類型
  • ChronoUnit - 計算出兩點之間的時間量,例如ChronoUnit.DAYS.between(t1, t2)
  • TemporalAdjuster - 例如date.with(TemporalAdjuster.firstDayOfMonth())

大多數狀況下,新的值類型由JDBC提供支持。有一小部分異常,如ZonedDateTime在SQL中沒有對應的(類型)。

等PM
等PM
翻譯於 3年前

2人頂

 翻譯的不錯哦!

集合API附件

實際上接口可以定義默認方法容許了JDK做者加入大量的附件到集合API接口中。默認實如今核心接口裏提供,而其餘更有效或更好的重載實現被加入到可適用的具體類中。

這裏是新方法的列表:

一樣, Iterator.remove() 如今有一個默認的, 會拋出異常的實現,使得它稍微容易地去定義不可修改的迭代器。

Collection.stream()和Collection.parallelStream()是流API的主要門戶。有其餘方法去生成流,但這些在之後會更爲長用。

List.sort(Comparator)的附件有點怪異。之前排序一個ArrayList的方法是:

?
1
Collections.sort(list, comparator);

這代碼是你在Java7裏惟一可選的,很是低效。它會複製list到一個數組裏,排序這個數組,而後使用ListIterator來把數組插入到新list的新位置上。

excepiton
excepiton
翻譯於 3年前

2人頂

 翻譯的不錯哦!

List.sort(比較器)的默認實現仍然會作這個,可是具體的實現類能夠自由的優化。例如,ArrayList.sort在ArrayList內部數組上調用了Arrays.sort。CopyOnWriteArrayList作了一樣的事情。

從這些新方法中得到的不只僅是性能。它們也具備更多的使人滿意的語義。例如, 對Collections.synchronizedList()排序是一個使用了list.sort的原子操做。你可使用list.forEach對它的全部元素進行迭代,使之成爲原子操做。

Map.computeIfAbsent使得操做相似多重映射的結構變得容易了:

?
1
2
3
4
5
6
7
8
// Index strings by length:
Map<Integer, List<String>> map =  new HashMap<>();  for (String s : strings) {
     map.computeIfAbsent(s.length(),
                         key ->  new ArrayList<String>())
        .add(s);
// Although in this case the stream API may be a better choice:
  Map<Integer, List<String>> map = strings.stream()
     .collect(Collectors.groupingBy(String::length));
super0555
super0555
翻譯於 3年前

2人頂

 翻譯的不錯哦!

增長併發API

有太多的連接能夠點擊,所以參看ConcurrentHashMap javadocs文檔以得到更多信息。

  • ConcurrentHashMap.reduce...
  • ConcurrentHashMap.search...
  • ConcurrentHashMap.forEach...
ForkJoinPool.commonPool()是處理全部並行流操做的結構。當你  須要的時候,它是一個好而簡單的方式去得到一個ForkJoinPool/ExecutorService/Executor對象。ConcurrentHashMap<K, V>徹底重寫。內部看起來它一點不像是Java7版本。從外部來看幾乎相同,除了它有大量批量操做方法:多種形式的減小搜索和forEach。
ConcurrentHashMap.newKeySet()提供了一個併發的java.util.Set實現。它基本上是Collections.newSetFromMap(new ConcurrentHashMap<T, Boolean>())的另外一種方式的重寫。
等PM
等PM
翻譯於 3年前

2人頂

 翻譯的不錯哦!

StampedLock是一種新型鎖的實現,極可能在大多數場景均可以替代ReentrantReadWriteLock。看成爲一個簡單的讀寫鎖的時候,它比RRWL的性能要好。它也爲「讀優化」提供了API,經過它你得到了一個功能有點弱,但代價很小的讀操做鎖的版本,執行讀操做,而後檢查鎖是否被一個寫操做設定爲無效。在Heinz Kabutz彙總的一系列幻燈片中,有更多關於這個類及其性能的細節(在這個系列幻燈片大約一半的地方開始的):"移相器和StampedLock演示"

CompletableFuture<T>是Future接口的一個很是棒的實現,它提供了無數執行(和串接)異步任務的方法。它特別依賴功能性的接口;lambdas是值得增長這個類的一個重要緣由。若是你正在使用Guava的 Future工具,例如Futures,ListenableFuture, 和 SettableFuture,那麼你可能會但願校驗CompletableFuture可否做爲潛在的替代選擇。

super0555
super0555
翻譯於 3年前

1人頂

 翻譯的不錯哦!

IO/NIO API的新增內容

簡單的說,這些API用於從文件和InputStreams獲取java.util.stream.Stream對象。不過它們與直接從常規的collection獲得的流有些不一樣,它們引入了兩個概念:

  • UncheckedIOException - 當有IO錯誤時拋出這個異常,不過因爲Iterator/Stream的簽名中不容許有IOException,因此它只能藉助於unchecked異常。
  • CloseableStream - 能夠(而且應該)定義在 try-with-resources 語句裏面的流。
zicode
zicode
翻譯於 3年前

1人頂

 翻譯的不錯哦!

反射和annotation的改動

Annotation容許在更多的地方被使用,例如List<@Nullable String>。受此影響最大的多是那些靜態分析工具,如Sonar和FindBugs。

JSR 308的網站解釋了增長這些改動的動機,介紹的不錯: "類型Annotation (JSR 308) 和 Checker框架"

zicode
zicode
翻譯於 3年前

1人頂

 翻譯的不錯哦!

其它翻譯版本(1)

Nashorn JavaScript 引擎

提案的摘要: JEP 174: Nashorn JavaScript 引擎

我對Nashorn沒什麼經驗,於是我對上面提案所描述的所知甚少。簡單的說,它是 Rhino 的接替者。Rhino 顯得有些老了,而且有點慢,開發者決定最好仍是從頭作一個。

zicode
zicode
翻譯於 3年前

0人頂

 翻譯的不錯哦!

其餘新增,涉及java.lang,java.util,和java.sql

這裏能夠介紹的太多了,只能挑一些最須要注意的項目。

ThreadLocal.withInitial(Supplier<T>) 能夠在定義thread-local變量時更好的進行初始化。以前你初始化變量時是這樣的:

?
1
2
3
ThreadLocal<List<String>> strings =  new ThreadLocal<List<String>>() {  @Override protected  List<String> initialValue() {  return new  ArrayList<>();
         }
     };
如今則是這樣: 
?
1
2
ThreadLocal<List<String>> strings =
     ThreadLocal.withInital(ArrayList:: new );

stream的API的返回值有一個可選的<T>,就像min/max, findFirst/Any, 以及reduce的某些形式。這樣作是由於stream中可能沒有任何元素,可是它要提供一個一致的API,既能夠處理「一些結果」,也能夠處理「沒有結果」。你能夠提供默認值,拋異常,或者只在有結果的時候執行一些動做。

zicode
zicode
翻譯於 3年前

1人頂

 翻譯的不錯哦!

它與Guava's Optional類很是很是的類似。它一點都不像是在Scala裏的操做,也不會試圖成爲之一,有類似的地方純屬巧合。 

旁白:Java 8's Optional和Guava's Optional最終如此的類似是頗有趣的事,儘管荒謬的辯論發生在這兩個庫。

"FYI.... Optional was the cause of possibly the single greatest conflagration on the internal Java libraries discussion lists ever."

Kevin Bourrillion在 response to "Some new Guava classes targeted for release 10"如實寫到:

"On a purely practical note, the discussions surrounding Optional have exceeded its design budget by several orders of magnitude."
Brian Goetz 在   response to "Optional require(s) NonNull"寫到。

StringJoinerandString.join(...)來得太晚了。他們來得如此之晚以致於大多數Java開發者已經爲字符串聯合編寫或發現了有用的工具,但這對JDK自己來講很每秒,由於最終本身實現這一點。每一個人都會遇到要求字符串鏈接的情形,咱們如今可以經過每一個Java開發者(事實上的)即將知道的標準的API來闡明,這也算是一件好事。
ComparatorsandComparator.thenComparing(...)提供了很是優秀的工具,基於鏈的比較和基於域的比較。像這樣:

?
1
2
people.sort(Comparators.comparing(Person::getLastName)
                        .thenComparing(Person::getFirstName));

這些新增功能提供了良好的,複雜的各類可讀的簡寫。大多數用例由JDK裏增長的 ComparisonChain和Ordering工具類來提供服務。對於什麼是有價值的,我認爲JDK版本比在Guava-ese裏功能等效的版本的可讀性好了不少。

相關文章
相關標籤/搜索