Java8新特性學習總結

Java8新特性學習總結

前言

最近深入研究了Java8的新特性,感覺Java8的這些新特性對Java編程的影響還是很大的,尤其是新的Lambda表達式,方法與構造函數引用,Stream API,新的Date/Time API,以及Java8對並行編程的擴展,都讓人耳目一新。其實這些新的特性在其它現代化的編程語言中早已出現,比如C#等,不過Java8引用了這些新的特性,能讓Java的代碼看起來更優雅、更高效,更符合現代語言的編程風格,也着實讓人興奮。

目錄

1.    函數式接口@FunctionalInterface

2.    接口的默認方法和靜態方法

3.    方法和構造函數引用

4.    Lambda表達式

5.    StreamsAPI

6.    並行數組

7.    新的Date/Time API

8.    註解的新特性—重複註解和擴展註解

9.    Base64類的標準化

10. 新的JavaScript腳本引擎Nashorn

11. 新的類型分析器jdeps命令

12. Java編譯器的新特性-parameters編譯參數的支持

正文

1.   函數式接口@FunctionalInterface

函數式接口是隻有一個抽象函數的接口,但是接口裏面可以有默認方法和靜態方法。函數式接口可以使用@FunctionalInterface註解來標明。 Lambda表達式的核心就是函數式接口和方法引用,每一個Lambda表達式其實都是對函數式接口的抽象函數的引用,示例如下:

@FunctionalInterface
public interface IConverter{
   
/**
     *
把內容爲數字的字符串轉換成數字
    
* @param value
    
* @return
    
*/
   
int convert(String value);

   
/**
     *
接口的默認方法示例
    
* @param str
    
*/
   
default void test(String str){
        System.
out.println("hello"+ str);
   
}

   
/**
     *
接口的靜態方法示例
    
* @param str
    
*/
   
static void test2(String str){
        System.
out.println("hello"+ str);
   
}

}

一個簡單的Lambda表達式示例如下:

List<String> list=new ArrayList<>();
list.add("item3");
list.add("item1");
list.add("item2");
//傳統寫法
list.sort(new Comparator<String>(){
   
@Override
   
public int compare(String str1, String str2) {
       
return str1.compareTo(str2);
   
}
})
;

//Lambda表達式寫法
list.sort((str1,str2)->{
    
return str1.compareTo(str2);
});

2.   接口的默認方法和靜態方法

從Java8開始,接口提供了對默認方法和靜態方法的支持,通過default關鍵字修飾的方法就是默認方法,示例如下:

@FunctionalInterface
public interface IConverter{
   
/**
     *
把內容爲數字的字符串轉換成數字
    
* @param value
    
* @return
    
*/
   
int convert(String value);

   
/**
     *
接口的默認方法示例
    
* @param str
    
*/
   
default void test(String str){
        System.
out.println("hello"+ str);
   
}

   
/**
     *
接口的靜態方法示例
    
* @param str
    
*/
   
static void test2(String str){
        System.
out.println("hello"+ str);
   
}

}

3.   方法和構造函數引用

方法引用的核心是類的函數聲明和只有一個抽象函數的接口的函數的聲明一致即可,詳情參照下面的示例:

@FunctionalInterface
public interface Supplier<T> {

   
/**
     * Gets a result.
     *
     * @return a result
     */
   
T get();
}

@FunctionalInterface
public interface Consumer<T> {

   
/**
     * Performs this operation on thegiven argument.
     *
     * @param
t the inputargument
     */
   
void accept(T t);
}


public class Person {
   
private String name="kgdwbb";
    public
Person(){

    }

   
public Person(String name){
       
this.name=name;
   
}

   
public staticvoid sayHello(){
        System.
out.println("Helloboy");
   
}

   
public staticvoid saySomething(String content){
        System.
out.println("Personsaid: "+content);
   
}

   
public void showName(){
        System.
out.println("my name is"+name);
   
}

   
public void showNewName(StringnewName){
        System.
out.println("my newname is "+newName);
   
}

   
public void showInfo(String name,String gender,int age){
        System.
out.println("name ="+name+" , gender = "+gender+" , age ="+age);
   
}
}

l  構造函數引用,示例如下:

Supplier<Person> supplier=Person::new;
supplier.get().showName();

靜態方法引用,示例如下:

//無參靜態方法引用
Runnable runnable=Person::sayHello;
new
Thread(runnable).start();

new
Thread(Person::sayHello).start();

//有參靜態方法引用
Consumer<String> consumer=Person::saySomething;
consumer.accept("hello boy");

 

非靜態方法引用,示例如下:

Person person=new Person("wubb");
Consumer<String> consumer=person::showNewName;
consumer.accept("xiaobei");

4.   Lambda表達式

Lambda表達式的核心就是函數式接口和方法引用,Lambda表達式的格式示例:

多行Lambda表達式格式:(參數1,參數2)->{}

單行Lambda表達式格式:無參數版:()->函數體,有參數版:(參數1,參數2)->函數體,其中函數體部分只有一行代碼,如果接口函數需要返回值,在函數體裏面也不用寫return語句,編譯器會默認生成對應的return語句

 

Lambda表達式示例:

List<String> list = new ArrayList<>();
list.add("item3");
list.add("item1");
list.add("item2");
//傳統寫法
list.sort(new Comparator<String>(){
   
@Override
   
public int compare(String str1, String str2) {
       
return str1.compareTo(str2);
   
}
})
;

//帶參數帶返回值的Lambda表達式寫法
list.sort((str1, str2) -> {
   
return str1.compareTo(str2);
});

//不帶參數不帶返回值的Lambda表達式寫法
new Thread(() -> {
    System.
out.println(Thread.currentThread().getName());
}).start();

//單行Lambda表達式寫法
IConverter converter = (strNum) ->Integer.valueOf(strNum);

5.   Streams API

Java8擴展了集合類,可以通過 Collection.stream() 或者Collection.parallelStream() 來創建一個Stream,前者是在單核CPU上執行,後者是在多核CPU上併發執行,在集合的數據量比較大的情況下,Collection.parallelStream()的速度更快,但是在集合的數據量不大的情況下,建議使用Collection.stream()的方式來操作集合,這樣速度會比Collection.parallelStream()更快,因爲省去了多核CPU的調度時間。

常用的Stream函數

List<String> list=new ArrayList<>();
list.add("item3");
list.add("item1");
list.add("item2");
list.add("item1");

filter過濾函數,用來對集合中的元素進行過濾,示例代碼如下:

String item= list.stream().filter((item)->item.indexOf("item2")>=0).findFirst().get();

sorted排序函數,用來對集合中的元素進行排序,示例代碼如下:

list.stream().sorted().forEach((item)->{
    System.
out.println(item);
});

forEach函數,用來對集合中的元素進行迭代遍歷,示例代碼如下:

list.stream().sorted().forEach((item)->{
    System.out.println(item);
});

map函數,用來對集合中的元素進行映射,示例代碼如下:

int max=list.stream().map((item)->{
    String num=item.replace(
"item","");
    return
Integer.valueOf(num);
}).max(Comparator.naturalOrder()).get();

distinct函數,用來對去除集合中的重複元素,示例代碼如下:

list.stream().distinct().forEach((item)->{
    System.
out.println(item);
});

collect函數,用來對集合中的元素進行可變縮減,示例代碼如下:

String str= list.stream().collect(Collectors.joining(","));

reduce函數,用來對集合中的元素進行縮減,示例代碼如下:

String str= list.stream().reduce((item1,item2)->item1+","+item2).get();

常用的parallelStream 函數

parallelStream函數和 stream函數是一樣的,唯一的區別如下:

list.parallelStream().forEach((item)->
{
    System.
out.println(item);
});

list.stream().forEach((item)->
{
    System.
out.println(item);
});

6.   並行數組

Java8對Arrays類進行了擴充,添加了幾個利用多核CPU對數組進行並行操作的方法,比如parallelSort,parallelSetAll,parallelPrefix等。

示例代碼如下:

final int arraySize=1000000;
int
[]array=new int[arraySize];
Arrays.parallelSetAll(array,(num)->ThreadLocalRandom.current().nextInt(arraySize));
Arrays.parallelSort(array);

7.   新的Date/Time API

Java8添加一個運行新的Date/Time API的包java.time包,裏面有最新的Date/Time API支持類,比如Clock,Instant,LocalDate,LocalTime,LocalDateTime類

Clock代表時鐘,示例代碼如下:

Clock clock=Clock.systemUTC();
long
ms=clock.millis();
Instant instant=clock.instant();
long
second=instant.getEpochSecond();

LocalDate代表本地時日期,示例代碼如下:

LocalDate localDate=LocalDate.parse("2017-04-23");
localDate=LocalDate.of(2017,4,23);
localDate=LocalDate.now();
localDate.plusDays(1);
localDate.minusDays(1);                                                                                                       

LocalTime代表本地時間:示例代碼如下:

LocalTime localTime=LocalTime.parse("12:10:30");
localTime=LocalTime.of(12,10,30);
localTime=LocalTime.now();
localTime.plusHours(1);
localTime.minusHours(1);

LocalDateTime代表本地時期和時間,示例代碼如下:

LocalDateTimelocalDateTime=LocalDateTime.parse("2017-04-23T12:10:30");
localDateTime=LocalDateTime.of(2017,4,23,12,10,30);
localDateTime=localDateTime.plusYears(1).plusMonths(1).plusDays(1).plusHours(1).plusMinutes(1).plusSeconds(1);
localDateTime=localDateTime.minusYears(1).minusMonths(1).minusDays(1).minusHours(1).minusMinutes(1).minusSeconds(1);

8.   註解的新特性—重複註解和擴展註解

重複註解

Java8允許我們把同一個類型的註解使用多次,只需要給該註解標註一下@Repeatable即可

@interface Hints {
   
Hint[] value();
}
@Repeatable(
Hints.class)
@
interface Hint {
    String
value();
}

使用包裝類當容器來存多個註解(老方法),示例代碼如下:

@Hints({@Hint("hint1"), @Hint("hint2")})
class Person {}

使用多重註解(新方法),示例代碼如下:

@Hint("hint1")
@Hint(
"hint2")
class Person {}

擴展註解

Java 8擴展了註解的上下文。現在幾乎可以爲任何東西添加註解:局部變量、泛型類、父類與接口的實現,就連方法的異常也能添加註解。示例代碼如下:

public class Annotations {
    @Retention( RetentionPolicy.RUNTIME )
    @Target( { ElementType.TYPE_USE
, ElementType.TYPE_PARAMETER} )
   
public @interface NonEmpty {
    }

   
public staticclass Holder< @NonEmpty T > extends @NonEmpty Object {
       
public void method() throws @NonEmpty Exception {
        }
    }

    
@SuppressWarnings( "unused")
   
public staticvoid main(String[] args) {
       
final Holder<String > holder = new @NonEmpty Holder<String >();
       
@NonEmpty Collection< @NonEmpty String >strings = new ArrayList<>();
   
}
}

9.   Base64類的標準化

在Java 8中,Base64編碼已經成爲Java類庫的標準。Base64類同時還提供了對URL、MIME友好的編碼器與解碼器(Base64.getUrlEncoder() / Base64.getUrlDecoder(), Base64.getMimeEncoder()/ Base64.getMimeDecoder())

示例代碼如下:

String txt="kgdwbb";
String strBase64= Base64.getEncoder().encodeToString(txt.getBytes("utf-8"));
byte
[]data=Base64.getDecoder().decode(strBase64);
String original=new String(data,"utf-8");

10.新的JavaScript腳本引擎Nashorn

在Java8中,默認的JavaScript引擎是Nashorn,示例代碼如下:

ScriptEngineManager scriptEngineManager=new ScriptEngineManager();
ScriptEngine scriptEngine=scriptEngineManager.getEngineByName("nashorn");
String result= scriptEngine.eval("function add(a,b){return a+b};add(2,3);").toString();

 

同時Java8還添加了一個基於Nashorn引擎的jjs命令,用來通過命令行執行JS腳本,示例如下:

jjs hello.js

11.新的類型分析器jdeps命令

jdeps是一個很有用的命令行工具。它可以顯示Java類的包級別或類級別的依賴。它接受一個.class文件,一個目錄,或者一個jar文件作爲輸入。jdeps默認把結果輸出到系統輸出(控制檯)上。示例如下:

jdeps zipfs.jar

12.Java編譯器的新特性-parameters編譯參數的支持

在Java8中,使用-parameters編譯參數,可以把函數的參數名編譯到java字節碼中,Java8以前,Java編譯器不支持這個參數,函數的名字就不能編譯到java字節碼中。

結尾

Java8的這些激動人心的特性將極大的影響java語言的發展,期待Java9,Java10等將會有更多令人興奮的新特性。

 

最後,感謝大家閱讀這篇文章,如果感覺哪裏有不足或錯誤的地方,歡迎隨時與我聯繫,我的QQ:624556373

參考資料

http://www.importnew.com/11908.html

http://www.jb51.net/article/48304.htm

http://www.open-open.com/lib/view/open1452343407151.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章