1. 程式人生 > >java8十大特性

java8十大特性

Java 8筆記

1、Lambda表示式

1.1什麼叫Lambda表示式:

Lambda表示式就是一段帶有引數的可執行語句塊

1.2Lambda表示式在java語言中引入了一個新的語法元素和操作符;

這個操作符為->,該操作符被稱為Lambda或箭頭操作符;它將Lambda

Fenwick兩個部分:

左側:指定了Lambda表示式需要的所有引數

右側:指定了Lambda體,即Lambda所需要執行的功能

1.3Lambda表示式的語法:

1.3.1、語法格式一:無參、無返回值,Lambda只需要一條語句

Runnable r1=() ->System.out.println(“hello word”);

1.3.2、語法格式二:帶一個引數

Consumer<String>  fun=(args) ->System.out.println(args);

1.3.3、語法格式三:Lambda只需要一個引數時,引數的小括號可以省略

Consumer<String>  fun=args ->System.out.println(args);

1.3.4、語法格式四:Lambda只需要一個引數時,並且有返回值

BinaryOperator<Long> bo=(x,y) ->{

System.out.println(“實現函式式介面方法”);

return x+y;

};

1.3.5、語法格式五:當Lambda體只有一條語句是,大括號和return可以省略

BinaryOperator<Long> bo=(x,y) ->x+y

1.3.6、語法格式六:

BinaryOperator<Long> bo=(Long x,Long y) ->{

System.out.println(“實現函式式介面方法”);

return x+y;

};

//Lambda體引數型別可以省略,因為可有編譯器推斷的出來,稱為型別推斷

簡單的舉個例子:

*下面程式碼是老版本的Java中是如何排列字串的:

List<String>  names=Arrays.asList(“peter”,”anna”,”mike”,”xenia”);

Collections.sort(names,new Comparator<String>);

@Override

Public int compare(String  a,String  b){

Return b.compareTo(a);

}

//只需要給靜態方法Collecyions.sort傳入一個List物件以及一個比較起來按指 定順序排列。通常做法都是建立一個匿名的比較器物件然後將其傳遞給sort 方法

*java8中就沒必要使用這種傳統的匿名物件的方式,java8提供了更簡潔的 語法,lambda表示式:

Collections sort(names,(a,b) ->b.compare(a))

2、函式式介面

2.1、什麼是函式式介面:

2.1.1、只包含一個抽象方法的介面,稱為“函式式介面”;

2.1.2、你可以通過Lambda表示式來建立該介面的物件,(若Lambda表示式丟擲一 個受檢查時異常,那麼該異常需要在目標介面的抽象方法上進行宣告)

2.1.3、可以在任意函式式上使用@FunctionalInterface註解,該註解可以檢查它是否 是一個函式式介面,

2.2java8中常用的全新介面

2.2.1Predicate介面(斷言型介面)

          Predicate介面只有一個引數,返回boolean型別,該介面包含多種預設方法   來將Predicate組合成其他複雜的邏輯(比如:與,或,非),包含方法boolean test(T t)

  程式碼如下:

   Predicate<String> predicate=(s) ->s.length()>0;

  Predicate.test(“foo”);//true

Predicate.negate().test(“foo”);//false

2.2.2Function<T,R>介面(函式型介面):T代表引數,R代表返回值

           Function介面有一個引數並且返回一個結果,並附帶了一些可以和其他函 數組合的預設方法(compose,andThen,包含方法 R apply (T t);

   程式碼如下:

Function<String,Integer> tolnteger=integer::valueOf;

Function<String,String> backToString=tointeger.andThen(String::valueOf);

backToString.apply(“123”);//123

2.2.3Supplier介面(供給型介面):返回一個任意泛型的值,Function不同的是該接 口沒有任何引數,包含方法T get();

程式碼如下:

Supplier<Person> personSupplier=person::new;

personSupplier.get();//new Person

2.2.4Consumer<T>介面(消費型介面):對型別為T的物件應用操作,包含方法void accept(T t);

程式碼如下:

Consumer<Person> greeter=(p) ->System.out.println(“hello”+p.firstName);

Greeter.accept(new Person(“Luke”,”Skywalker”));

3、方法引用和構造引用

3.1、方法引用

*當要傳遞給Lambda體的操作,已經有實現的方法了,可以使用方法引用!

 (實現抽象方法的引數列表,必須與方法引用的引數列表保持一致!)

*方法引用:使用操作符”::” ,將方法名和物件或類的名字分開。

如下三種使用情況:

*物件::例項方法

*類::靜態方法

*類::例項方法

1:

(x) ->System.out.println(x);

等同於

System.out::println;

2

Compare((x,y) ->x.equals(y),”abc”,”abc”)

等同於

Compare(String::equals”abc”,”abc”)

3.2、建構函式引用

用函式式介面相結合,自動與函式式介面種方法相容,可以把構造器引用賦值給定 義的方法,構造器引數列表要與介面中抽象方法的引數列表一致。

例子:

Function<Integer,MyClass> fun=(n) ->new MyClass(n);

等同於

Function<Integer,MyClass> fun=MyClass::new;

3.3、陣列引用

格式:Type[]::new

例子:Function<Integer,MyClass> fun=(n) ->new Integer[n];

等同於

Function<Integer,MyClass> fun=Integer::new;

4、Stream API

4.1、流(Stream)到底是什麼

是資料渠道用於操作資料來源(集合,陣列等)所生成的元素序列

(集合講究的是資料,流講究的是計算)

注意:

  *Stream自己不會儲存元素

*Stream不會改變源物件;相反,他們會反回持有結果的新流(Stream)

*Stream操作是延遲執行的,需要結果的時候才會執行

4.2Stream操作的三個步驟

4.2.1、建立Stream

一個數據源(如:集合、陣列),獲取一個流

4.2.2、中間操作

一箇中間操作鏈,對資料來源的資料進行處理

4.2.3、終止操作(終端操作)

一個終止操作,執行中間操作鏈,併產生結果

------>一系列的中間處理操作(map(),filter())------>終止操作

4.3Stream怎麼用,

*Java8擴充套件了集合類,可以通過Collection.stream()或者Collection.parallelStream() 建立一個Stream

下面舉例子說明:

List<String > stringCollection=new ArrayList<>();

stringCollection.add(“ddd2”);

stringCollection.add(“aaa2”);

stringCollection.add(“bbb1”);

stringCollection.add(“aaa1”);

stringCollection.add(“bbb3”);

stringCollection.add(“ccc”);

stringCollection.add(“bbb2”);

stringCollection.add(“ddd1”);

4.3.1:filter方法過濾:

StringCollection.stream()

  .filete((s) ->s.startsWith(“a”))

  .forEach(System.out::println);//輸出結果”aaa2”,”aaa1”

4.3.2sort排序

排序是個中間操作,返回的實拍序號後的stream,如果不指定一個字定義的 Comparator則會使用預設排序;

程式碼如下:

StringCollection.stream()

  .sorted()

  Filter((s) ->s.startsWith(“a”))

  .forEach(System.out::println);//輸出結果”aaa1”,”aaa1”

//排序只建立一個排序好後的stream,而不會影響原來的資料來源,排序號之後源數 StringCollection是不會修改的;

4.3.3map對映

中間操作map會將元素根據指定的Function介面來依次將元素轉成另外的物件,

下面的示例展示了將字串轉換成大寫字串,你也可以通過map來將物件轉換 成其他型別,map返回的Stream型別是根據你map傳遞進去的函式的返回值決定的

例子:

StringCollection.stream()

 .map(String::toUpperCase)

  .sorted((a,b) ->b,compareTo(a))

  .forEach(System.out::println);

//輸出結果:”DDD2”,”DDD1”,”CCC”,”BBB3”,”BBB2”,”AAA2”,”AAA1”

4.3.4Match匹配

Stream提供了多種匹配操作,允許檢測制定的Predicate是否匹配整個Stream ,

所有的匹配操作都是最終操作,並且返回一個boolean型別的值

例子:

Boolean anyStartsWithA=

stringCollection.stream()

.anyMatch((s) ->s.startsWith(“a”))

System.out.println(anyStartsWithA);//true

4.3.5count計數

技術是一個最終操作,返回Stream中元素的個數,返回值型別是long

例子:

Long startsWithB=

stringCollection.stream()

 .filter((s)->s.startsWith(“b”))

 .count();

SystemOut.println(startsWithB);//3

4.3.6、規約

這是一個人最終操作,允許通過指定的函式來將stream中的多個元素規約為一個 元素,規約後的結果是通過Optional介面表示的

程式碼:

Optional<String> reduced=

stringCollection.stream()

.sorted()

.reduce((s1,s2) ->s1+”#”+s2);

Reduced.ifPresent(System.out::println);

//輸出結果:“aaa1#aaa2#bbb2#bbb3#ccc#ddd1#ddd2

4.3.7、並行Streams

Stream有序列和並行兩種,序列Stream上的操作是在一個執行緒中依次完成,

而並行Stream則是在多個執行緒上同時執行

通過並行Stream可以提升效能,可以減少執行時間,他沒有空閒的執行緒核

一個執行緒執行完了,它會去從別的別的執行緒核末尾偷一個執行

5、介面中的預設方法與靜態方法

5.1、介面的預設方法

Java8允許我們給介面新增一個非抽象的方法實現,只需要使用default關鍵字即可,

這個特徵有叫做擴充套件方法

程式碼如下:

Interface Formula{

double calculate(int a );

default double sqrt(int a ){

Return Math.sqrt(a);

}

}

在上面Formula介面在擁有calculate方法之外同時還定義了sqrt方法,實現了 Formula介面的子類只需要實現一個calculate方法,預設方法sqrt將在子類上可以 直接使用。

*介面預設方法”類優先”原則:

若一個介面中定義了一個預設的方法,而另外一個父類或介面中又定義了一個同名 的方法時。

---選擇父類的方法,如果一個父類提供了具體的實現,那麼介面中具有相同名稱和   引數的預設方法會忽略

---介面衝突,如果一個父介面提供一個預設的方法,而另外一個介面也提供了一個   具有相同名稱和引數列表的方法(不管方法是不是預設方法),那麼必須覆蓋該方   法來解決衝突

簡單例子:

Interface MyFun(){

Defalut String getName()

 Return “hello”;

}

}

Interface  Named(){

Defalut String getName()

 Return “hello word”;

}

}

Class MyClass  implements MyFun, Named(){

 Public String getName(){

Return Named.super.getName()

}

}

5.2靜態方法

介面中允許新增靜態方法

例子:

Interface Nmaed(){

Public Integer Myfun();

Defalut String getName(){

 Return “hello”;

]

Static void show(){

System .out.println(“靜態方法引用”);

}

}

6、新時間日期API

6.1、在java8中,添加了一個新包:java.time,它提供了結構良好的API來處理時間和日 期;

新的API:java.time,5個包組成:

.java.time              --包含值物件的基礎包

.java.time.chrono   --提供對不同的日曆系統的訪問

.java.time.format   --格式化和解析時間日期

.java.time.temporal   --包括底層框架和擴充套件特性

.java.time.zone   --包含時區支援的類

*以前版本存在的問題

1、可變性:所有的日期類都是可變的,執行緒不安全

2、偏移性:Data中的年份是從1990開始的,而月份都是從0開始的

3java的日期/時間類的定義並不一致,在Java.UtilJava.sql的包中都有日期類, 此為用於格式化和解析的類在java.text包中定義

4java.util.Date 同時包含日期和時間,而java.sql.Date僅包含日期,將其納入java.sql

          包並不合理,另外這連個類都有相同的名字,本身設計不合理

5、對於時間、時間戳、格式化以及解析,並沒有一些明確定義的類。對於格式化 和解析的需求,我們有java.text.DateFormat類被用於此類需求

6、日期類並不提供國際化,沒有時區支援,因此java引入了java.util.Calendar java.util.TimeZone類,但他們同樣存在上述所有的問題

*LocalDate類方法例子如下:

LocalDate date=LocalDate .of(2014,Month.JUNE,10);

Int year=date.getYear();//2014

Month month=date.getMonth();//6

Int dom=date.getDayOfMonth();//10

DayOfWeek dow=date.getDayOfWeek();//星期二

Int len=date.lengthOfMonth();//30(6月份的天數)

bolean leap=date.isLeapYear();//false(不是閏年)

*LocalTime類的用法跟LacalDate相似:

LocalTime time=LocalTime.of(20,30);

Int hour=date.getHour();//20

Int minute=date.getMinute();//30

Time=time.withSecound(6);//20:30:06

Time=time.plusMinutes(3);//20:33:06

*LocalDateTime類是LocalDateLocalTime的簡單組合,它表示一個跟時區無關的日期 和時間;LocalDateTime可以直接建立,或者組合時間和日期:

例子:

LocalDateTime dt1=LocalDateTime.of(2014,Month.JUNE,10,20,30);

LocalDateTime dt2=LocalDateTime .of(date,time);

LocalDateTime dt2=date.atTime(20,30);

LocalDateTime dt4=date.atTime(time);

7、型別註解與重複註解

7.1什麼是型別註解

7.1.1Java8ElementType列舉增加了TYPE_PARAMETERTYPE_USE兩個列舉值,從而可以使 @Target(ElementType_TYPE_USE)修飾註解定義,這種註解稱為型別註解,可以用在任何使 用到型別的地方;

  * ElementType.TYPE_PARAMETE表示註解能寫在型別變數的的宣告語句中(

   class  MyClass{...}).

      *ElementType.TYPE_USE表示註解註解能寫在使用型別的任何語句中(例如宣告語

           句、泛型和強制轉換語句中的型別)

7.1.2、在Java8之前,註解只能在宣告的地方使用,比如類、方法、屬性;

java8裡面,註解可以應用在任何地方;

        簡單的舉幾個例子:

*建立類例項

New @interned MyObject();

*型別對映

myString=(@NonNull String) str;

@Encrypted String data;

* 泛型

List<@NonNull String> strings;//防止非空,java8裡面還沒有內建這個註解,    編譯時會報錯要配合框架使用(checker      framework)

MyGRAph=(@Immutable Graph)  tmpGraph ;

7.2什麼是可重複註解

*允許在同一申明型別(類、屬性、方法)的多次使用同一個註解

例子:

*Java8之前也有重複註解的解決方案,但可讀性不是很好,

Java8裡面的做法:

@Repeatable(MyAnnotations.class)

Public @interface MyAnnotation{

String role();

}

Public @interface MyAnnotations{

MyAnnotation[] role();

}

Public class Repeat{

@MyAnnotation(role=”Admin”)

@MyAnnotation(role=”Admin”)

public void TestAnnotations(){

}

}

*Java8不同地方的是,建立重複註解MyAnnotation時,加上@Repeatable,指向儲存

註解MyAnnotations(給註解建立一個容器),在使用時候,直接可以重複使用 MyAnnotation

註解

8、Optional

8.1*OPtional(java.util.Optional)是一個容器類,可以為null的容器物件,如果值存在則   isPresent()方法會返回true,呼叫get()方法會返回該物件

*OPtional類的引入很好的解決了空指標異常

8.2of方法

可以用of方法通過工廠方法建立Optionnal類,建立物件時傳入的引數不能為null,

如果傳入引數為null,則丟擲NullPointerException

簡單例子:

//呼叫工廠方法建立Optional例項

Optional<String> name=Optional.of(“aaaa”);

//傳入引數為null,丟擲NullPointerException

Optional<String> someNull=Optional.pf(null);

8.3ofNullable方法

為指定的值建立一個Optionnal,如果指定的值為null,則返回一個空 的 Optional;

ofNullof方法相似,唯一的區別是可以接受引數為null的情況

示例如下:

//下面建立一個不包含任何值的Optional例項

//例如值為‘null

Optional  empty=Optional.ofNull(null);

8.4isPresent方法

如果值存在返回true,否則返回false

例子:

//isPresent方法用來檢查Optional例項中是否包含值

If(name.isPresent()){

//Optional例項類呼叫get()返回存在的值

System.out.println(name.get());

}

8.5get方法

如果Optional有值則將其返回,否則丟擲NosuchElementException.

8.6orElse方法

如果有值則將其返回,否則返回指定的其他值

8.7orElesGet方法

orElesGetorElse方法類似,區別在於得到的預設值。

orElse方法見傳入的字串作為預設值,orElesGet方法可以接受Supplier介面的實 現來生成預設值

8.8orElseThrow方法

如果有值則將其返回,否則丟擲Supplier介面建立的異常

8.9map方法

如果有值,則對其執行呼叫mapping函式得到返回值,如果返回值不為null,則創 建包含mapping返回值的Optional作為map方法的返回值,否則返回空Optional.

程式碼如下:

//map方法執行傳入的lambda表示式引數對Optional實力的值進行修改

//lambada表示式的返回值建立新的Optional例項作為map方法的返回值

Optional<String> upperName=name.map((value) ->value.toUpperCase());

System.out.println(upperName.orElse(“No value found”));

8.10flatMap方法

    如果有值,為其執行mapping函式返回Optional型別返回值,否則返回空Optional;

flatMapmap(Funtion)方法類似,區別在於flatMap中的mapper返回值必須是 Optional,呼叫結束時,flatMap不會對結果用Optional封裝

8.11filter方法

通過傳入限定條件對Optional例項的值進行過濾

簡單的舉個例子:

//filter方法檢查給定的Option值是否滿足某些條件

//如果滿足則返回同一個Optional例項,否則返回空Optional

Optional<String> longName=name.filter((value) ->value.length()>6);

System.out.println(longName.orElse(“The name less than 6characters”))