Java8的新特性有:默認方法、函數式接口、lambda表達式、方法引用、Stream、Optional、日期API。程序員
1、默認方法:app
接口中的方法能夠有方法體,可是必需要有static或者default修飾,其餘的方法都爲抽象方法,由static修飾的方法不能被子接口繼承 、方法不能被覆寫,只能經過類名.方法名調用;由default修飾的方法能夠被子接口繼承,也能夠被覆寫,調用經過實現類的對象調用。dom
2、函數式接口:ide
接口中有且僅有一個抽象方法,通常都有@FuntionalInterface註解,即便沒有註解它仍是函數式接口。函數
常見的函數式接口:Comparetor、Runnable。spa
3、lambda表達式:指針
能夠當作是對匿名內部類的簡寫,使用lambda表達式的接口必須爲函數式接口;code
注:匿名內部類會編譯產生兩個class文件,但lambda表達式只會編譯產生一個class文件。對象
(參數1,參數2…)表示參數列表;->表示鏈接符;{}內部是方法體
一、=右邊的類型會根據左邊的函數式接口類型自動推斷;
二、若是形參列表爲空,只需保留();
三、若是形參只有1個,()能夠省略,只須要參數的名稱便可;
四、若是執行語句只有1句,且無返回值,{}能夠省略,如有返回值,則若想省去{},則必須同時省略return,且執行語句也保證只有1句;
五、形參列表的數據類型會自動推斷;blog
6、lambda表達式中使用的局部變量默認會被final修飾,無論這個局部變量是在lamdba表達式裏定義的仍是在表達式外定義的。所以只要是lambda表達式中使用過的局部變量就不能再修改了,無論在什麼位置。
4、方法引用:
4.1 構造方法引用:
//匿名內部類 PersonFacotry facotry = new PersonFacotry() { @override public Person createPerson(String name, Integer age){ //其餘操做 return new Person (name, age); } }; //lambda表達式寫法 PersonFacotry facotry1 = (name, age) -> new Person (name, age); //lambda表達式簡寫(這種寫法的函數式接口有幾個參數,就調用其對應參數個數的構造方法) PersonFacotry facotry2 = Person:: new; Person person = facotry.createPerson ( name: "某某某", age: 100) ; System.out.println(person);
4.2靜態方法引用
public class Test{ public static void main(string[] args) { //匿名內部類方式 Parseinterface pil = new ParseInterface(){ @override public int parse(string str) { return Integer.parselnt(str); } }; // Lambda表達式常規寫法 ParseInterface pi2 = str->Integer.parseInt(str); // Lambda表達式簡寫 ParseInterface pi3 = Integer::parseInt; } }
4.3實例方法引用
Java1.8提供了一個函數式接口Function,接受兩個參數
匿名內部類方式
string str ="Hello.world"; //匿名內部類的方式 Function<String,Boolean> func1= new Function<String,Boolean> (){ @override public Boolean apply(strinq suffix) { return str.endswith (suffix); } };
Lambda表達式常規寫法
// Lambda表達式常規寫法 String str = "Hello.world"; Function<String,Boolean> func3 = t -> str.endsWith(t); System.out.println(func3.apply("world"));
Lambda表達式簡寫
// Lambda表達式常規寫法 String str = "Hello.world"; Function<String,Boolean> func2 = t -> str::endsWith; System.out.println(func2.apply("world"));
5、Stream:
Java 8 API添加了一個新的抽象稱爲流Stream,Stream API能夠極大提升Java程序員的生產力,讓程序員寫出高效率、乾淨、簡潔的代碼。
注意:和IO中的流是徹底不同的。
在 Java 8 中, 集合接口有兩個方法來生成流:
stream() − 爲集合建立串行流。(經常使用)
parallelStream() − 爲集合建立並行流。
Stream經常使用方法:
ForEach:
Stream 提供了新的方法 'forEach' 來迭代流中的每一個數據。如下代碼片斷使用 forEach 輸出了10個隨機數:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map:
map 方法用於映射每一個元素到對應的結果,如下代碼片斷使用 map 輸出了元素對應的平方數:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 獲取對應的平方數 List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filter:
filter 方法用於經過設置的條件過濾出元素。如下代碼片斷使用 filter 方法過濾出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 獲取空字符串的數量
int count = strings.stream().filter(string -> string.isEmpty()).count();
limit:
limit 方法用於獲取指定數量的流。 如下代碼片斷使用 limit 方法打印出 10 條數據:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted:
sorted 方法用於對流進行排序。如下代碼片斷使用 sorted 方法對輸出的 10 個隨機數進行排序:
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
並行(parallel)程序:
parallelStream 是流並行處理程序的代替方法。如下實例咱們使用 parallelStream 來輸出空字符串的數量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 獲取空字符串的數量 int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
咱們能夠很容易的在順序運行和並行直接切換。
Collectors:
Collectors 類實現了不少歸約操做,例如將流轉換成集合和聚合元素。Collectors 可用於返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("篩選列表: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合併字符串: " + mergedString);
6、Optional:
Optional對象能夠爲空,因此Optional 類的引入很好的解決空指針異常。
經過如下實例來了解Optional類的使用:
Public class User{ private String name; private String password; .... }
以往的判斷方式:
public class Mytest{ public static void main(String[] args){ User user = new User(); User.setPassword(「admin」); String name = getPwd(user); System.out.println(name); } public static String getPwd(User u){ if(u==null){ return 「unknown」; } return u.getPassword(); }
使用Optional:
public static String getPwd(User u){ return Optional.ofNullable(u) .map(user->user.getPassword()) .orElse(「unknown」); };
7、日期Api:
Jdk1.8給咱們提供了三個本地日期時間類:LocalDate、LocalTime 和 LocalDateTime 類。
在不須要處理時區問題的時候,使用本地日期時間API(LocalDate、LocalTime 和 LocalDateTime) :
// 獲取當前的日期時間 LocalDateTime currentTime = LocalDateTime.now(); System.out.println("當前時間: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); Month month = currentTime.getMonth(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds);
在須要處理時區的時候,使用時區的日期時間API(ZonedDateTime ):
ZonedDateTime dd= ZonedDateTime.now(); System.out.println(dd); ZonedDateTime date1 = ZonedDateTime.parse(dd.toString()); System.out.println("date1: " + date1); ZoneId id = ZoneId.of(ZoneId.SHORT_IDS.get("CTT")); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("當期時區: " + currentZone);