學習java8的新特性之前,簡單看了下從java5開始歷代版本的新特性,都是別人總結的。
java5、java6、java7、java8的新特性
http://blog.csdn.net/samjustin1/article/details/52268004
其中java 7 第四點介紹System.getJavaIoTempDir()....這些方法已經沒有了,用System.getProperties()可以達到同樣的目的。
比如System.getUserDir() 可用System.getProperties(“user.dir”)代替。
Map map = {name:“xxx”,age:18};//不可行
作者是個復制粘貼黨,估計都沒試這些特性是否真添加了。
Java8新特性
http://www.cnblogs.com/chengJAVA/p/6113649.html
1.函數式接口
這里有個坑--哪怕有很多默認方法,只要接口只定義了一個抽象方法,它就仍然是一個函數式接口。
2.Lambda表達式
3.增強接口(和抽象類很像)
4.stream流的操作(和scala類似)
5.IO/NIO的改進新增的API
6.國際化(這個針對世界時區的),date類的新API (下面幾個實例)
LocalDate.now();//獲取localdate LocalDate.now().plusDays(-1L).atStartOfDay();//前一天凌晨0點 LocalDate.now().atTime(LocalTime.NOON);//今天中午12點 LocalDate.now().atTime(OffsetTime.now().plusHours(-1));//今天前一小時 LocalDate.now().atTime(8, 30);//設置時間 LocalDate.now().atTime(8, 30).toLocalDate();//提取日期 LocalDate.now().atTime(8, 30).toLocalTime();//提取時間 LocalDate.parse("2020-10-01");//解析字符串時間 LocalDate.parse("20201005",DateTimeFormatter.ofPattern("yyyyMMdd"));//解析字符串時間
Instant.now().toEpochMilli();//獲取當前時間戳
System.out.println(Clock.systemUTC());//格林尼治時區
System.out.println(Clock.systemDefaultZone());//默認時區
System.out.println(Clock.systemDefaultZone().getZone());//獲取當前時區
System.out.println(Clock.systemDefaultZone().millis());//時間戳
之前處理時間都是用SimpleDateFormat和Calendar類來回轉換,現在方便多了。
並行與共享的可變數據,這兩個要點(沒有共享的可變數據,將方法和函數即代碼傳遞給其他方法的能力)是我們平常所說的函數式編程范式的基石
值是Java中的一等公民 ----可傳遞
其他很多Java概念(如方法和類等)則是二等公民 ----編程語言中的其他結構也許有助於我們表示值的結構,但在程序執行期間不能傳遞,因而是二等公民。
Java 8的方法引用 ??
與用對象引用傳遞對象類似(對象引用是用new創建的),在Java 8里寫下File::isHidden的時候,你就創建了一個方法引用,你同樣可以傳遞它。
謂詞 (predicate)
在數學上常常用來代表一個類似函數的東西,它接受一個參數值,並返回true或false。即一個返回boolean值的函數
從傳遞方法到 Lambda
1.方法引用---要用它的話,你可以寫:
filterApples(inventory, Apple::isGreenApple);
但是用前要定義isGreenApple方法
public static boolean isGreenApple(Apple apple) {
return "green".equals(apple.getColor());
}
2.把方法作為值來傳遞顯然很有用,但要是為類似於isHeavyApple和isGreenApple這種可能只用一兩次的短方法寫一堆定義有點兒煩人。
所以引入了一套新記法(匿名函數或Lambda)
可以這樣寫
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
也可以這樣
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
還可以這樣
filterApples(inventory, (Apple a) -> a.getWeight() < 80 ||"brown".equals(a.getColor()) );
二、為了更好地利用並行,Java 8中有一整套新的類集合API——Stream
1.api
2.Collections和Streams之間做轉換
內部迭代與外部迭代
和Collection API相比,Stream API處理數據的方式非常不同。用集合的話,你得自己去做迭代的過程。你得用for-each循環一個個去迭代元素,然后再處理元素。我們把這種數據迭代的方法稱為外部迭代。
相反,有了Stream API,你根本用不着操心循環的事情。數據處理完全是在庫內部進行的。我們把這種思想叫作內部迭代。
並行(多線程)共享變量
Stream API如何解決這個問題的?
Java 8也用Stream API(java.util.stream)解決了這兩個問題:集合處理時的套路和晦澀,以及難以利用多核。
(1)在兩個CPU上篩選列表,可以讓一個CPU處理列表的前一半,第二個CPU處理后一半,這稱為分支步驟。
(2) CPU隨后對各自的半個列表做篩選。
(3)最后一個CPU會把兩個結果合並起來 -----整體思想和mapReduce類似,分片處理再聚合
對比舊的集合Collection和"新集合"Stream
Collection主要是為了存儲和訪問數據,而Stream則主要用於描述對數據的計算。
作者建議 --篩選一個Collection(將上一節的filterApples應用在一個List上)的最快方法常常是將其轉換為Stream,進行並行處理,然后再轉換回List。
List<Apple> heavyApples =
inventory.stream().filter((Apple a) -> a.getWeight() > 150) //並行則使用parallelStream() 這個方法,stream()是串行運行
.collect(toList()); //把普通集合處理為Stream,計算完畢后再轉為普通集合。
默認方法的引出
若要使用上面的代碼.stream()方法。在Java 8之前, List<T>並沒有stream或parallelStream方法,它實現的Collection<T>接口也沒有,因為當初還沒有想到這些方法嘛!可沒有這些方法,這些代碼就不能編譯。換作你自己的接口的話,最簡單的解決方案就是讓Java 8的設計者把stream方法加入Collection接口,並加入ArrayList類的實現。 但是接口改變,之前的項目工程里所有的類都要去實現這個接口的新方法。
這下你就進退兩難了:你如何改變已發布的接口而不破壞已有的實現呢?
這就給接口設計者提供了一個擴充接口的方式,而不會破壞現有的代碼。 Java 8在接口聲明中使用新的default關鍵字來表示這一點。(牛逼!)
在Java 8里,你現在可以直接對List調用sort方法。它是用Java 8 List接口中如下所示的默認方法實現的,它會調用Collections.sort靜態方法:
default void sort(Comparator<? super E> c) { Collections.sort(this, c); }
這意味着List的任何實體類都不需要顯式實現sort,而在以前的Java版本中,除非提供了sort的實現,否則這些實體類在重新編譯時都會失敗。
- 如果在好幾個接口里有多個默認實現,是否意味着Java中有了某種形式的多重繼承?
- Optional<T>
- 模式匹配
理解行為參數化和傳遞代碼的"演化方式"
java8前怎么做?用匿名內部類怎么實現?方法引用?再到Lambda表達式。