天天看點

java8 list 轉map_JAVA 8與JAVA 11到底該怎麼選?

很多初學Java的小夥伴經常咨詢:

  • 到底該安裝哪個版本的JDK比較好?
  • Java 8到底還夠不夠用?
  • Java 11究竟有什麼改進?
  • 是不是Java版本越新越好?
  • ……

是這樣,官網現在其實都已經出到Java 13版本了,并且提供下載下傳使用。

java8 list 轉map_JAVA 8與JAVA 11到底該怎麼選?

但目前市場上主流的

穩定版

當然還得屬

Java 8

Java 11

,而目前大部分公司的生産環境還是Java 8居多。是以如果從自學角度出發,我覺得這兩個版本都OK,其他中間的一些比如Java 9、Java 10這些非穩定版就不用考慮了。

Java11 vs Java8

java8 list 轉map_JAVA 8與JAVA 11到底該怎麼選?

Java 11相對于Java 8确實有一部分進化,除了有很多内部的更新(比如開銷和時延更低的GC、TLS1.3加持等等)之外,對于初學使用者來說也有一些語言使用層面的進化。

正好最近我在自己的個人小項目上嘗試更新使用了一下Java 11(公司項目咱也不敢動、也不敢問,隻好動自己的個人項目),是以本文從實際代碼編寫角度來大緻體驗一下我個人使用Java 11之後相對Java 8所感覺到的一些比較深刻的進化,官方文檔裡說得也非常清楚了:https://docs.oracle.com/en/java/javase/11/

我這次實驗裝的Java 11版本是11.0.6:

java8 list 轉map_JAVA 8與JAVA 11到底該怎麼選?
下文将要實驗驗證的一些新特性其實也并非Java 11才引入,很多其實在Java 9和Java 10時就已經引入,隻不過到了Java 11這個穩定版才沉澱下來。

變量類型推斷

新版Java引入了一個全新的類型關鍵字var,用var來定義的變量不用寫具體類型,編譯器能根據=右邊的實際指派來自動推斷出變量的類型:

1、普通局部變量
var name = "codesheep"; // 自動推斷name為String類型
System.out.println(name);           
怎麼樣?是不是有一種在使用類似JavaScript這種弱類型語言的錯覺?
2、for循環中使用
var upList1 = List.of( "劉能", "趙四", "謝廣坤" );
var upList2 = List.of( "永強", "玉田", "劉英" );
var upList3 = List.of( "謝飛機", "蘭妮", "蘭娜" );
var upListAll = List.of( upList1, upList2, upList3 );
for( var i : upListAll ) { // 用var接受局部變量的确非常簡潔!
    for( var j : i  ) {
        System.out.println(j);
    }
}
           

這地方就能看出用var定義局部變量的優勢了,假如這個例子中集合裡的元素類型更為複雜,是類似List<List<String>>這種嵌套類型的話,var定義就非常簡潔明了!

3、當然,有些情況是不能使用的

var類型變量一旦指派後,重新賦不同類型的值是不行的,比如:

var name = "codesheep";
name = 666;  // 此時編譯會提示不相容的類型           

定義var類型變量沒有初始化是不行的,比如:

var foo;  // 此時編譯會提示無法推斷類型
foo = "Foo";           

另外,像類的成員變量類型、方法入參類型、傳回值類型等是不能使用var的,比如:

public class Test {
    
    private var name; // 會提示不允許使用var           

    public void setName( var name ) { // 會提示不允許使用var
        this.name = name;
    }

    public var getName() { // 會提示不允許使用var
        return name;
    }
     
}           

官方HTTP Client加持

是的!

現在JDK官方就自帶HTTP Client了,位于java.net.http包下,支援發送同步、異步的HTTP請求,這樣一來,以前咱們常用的HTTP請求用戶端諸如:OKHttp、HttpClient這種現在都可以退下了!

發送同步請求:

var request = HttpRequest.newBuilder()
        .uri( URI.create("https://www.codesheep.cn") )
        .GET()
        .build();
// 同步請求方式,拿到結果前會阻塞目前線程
var httpResponse = HttpClient.newHttpClient()
        .send( request, HttpResponse.BodyHandlers.ofString());
System.out.println( httpResponse.body() ); // 列印擷取到的網頁内容           

發送異步請求:

CompletableFuture<String> future = HttpClient.newHttpClient().
        sendAsync( request, HttpResponse.BodyHandlers.ofString() )
        .thenApply( HttpResponse::body );
System.out.println("我先繼續幹點别的事情...");
System.out.println( future.get() ); // 列印擷取到的網頁内容           

當然你也可以自定義請求頭,比如攜帶JWT Token權限資訊去請求等:

var requestWithAuth = HttpRequest.newBuilder()
        .uri( URI.create("http://www.xxxxxx.com/sth") )
        .header("Authorization", "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxNTIwNTE2MTE5NiIsImNyZWF0ZWQiOjE1ODMzMTA2ODk0MzYsImV4cCI6MTU4MzM5NzA4OSwidXNlcmlkIjoxMDAwNH0.OE9R5PxxsvtVJZn8ne-ksTb2aXXi7ipzuW9kbCiQ0uNoW0fJJr_wckLFmgDzxmBs3IdzIhWDAtaSIvmTshK_RQ")
        .GET()
        .build();
var response = HttpClient.newHttpClient()
        .send( requestWithAuth, HttpResponse.BodyHandlers.ofString() );
System.out.println( response.body() ); // 列印擷取到的接口傳回内容           

String處理增強

新版字元串String類型增加了諸如:isBlank()、strip()、repeat()等友善的字元串處理方法

String myName = " codesheep ";
System.out.println( "  ".isBlank() ); // 列印:true
System.out.println( "  ".isEmpty() ); // 列印:false

System.out.println( myName.strip() );         // 列印codesheep,前後空格均移除
System.out.println( myName.stripLeading() );  // 列印codesheep ,僅頭部空格移除
System.out.println( myName.stripTrailing() ); // 列印 codesheep,僅尾部空格移除
System.out.println( myName.repeat(2) );       // 列印 codesheep  codesheep           

集合增強

主要是增加了諸如of()和copyOf()等方法用于更加友善的

建立

複制

集合類型

var upList = List.of( "劉能", "趙四", "謝廣坤" );
var upListCopy = List.copyOf( upList );
System.out.println(upList);     // 列印 [劉能, 趙四, 謝廣坤]
System.out.println(upListCopy); // 列印 [劉能, 趙四, 謝廣坤]

var upSet = Set.of("劉能","趙四");
var upSetCopy = Set.copyOf( upSet );
System.out.println(upSet);      // 列印 [趙四, 劉能]
System.out.println(upSetCopy);  // 列印 [趙四, 劉能]

var upMap = Map.of("劉能","58歲","趙四","59歲");
var upMapCopy = Map.copyOf( upMap );
System.out.println(upMap);      // 列印 {劉能=58歲, 趙四=59歲}
System.out.println(upMapCopy);  // 列印 {劉能=58歲, 趙四=59歲}           

函數式程式設計增強

我印象最深的是對Stream流增加了諸如takeWhile()和dropWhile()的截止結算方法:

var upList = List.of( "劉能", "趙四", "謝廣坤" );

// 從集合中依次删除滿足條件的元素,直到不滿足條件為止
var upListSub1 = upList.stream()
        .dropWhile( item -> item.equals("劉能") )
        .collect( Collectors.toList() );
System.out.println(upListSub1);  // 列印 [趙四, 謝廣坤]

// 從集合中依次擷取滿足條件的元素,知道不滿足條件為止
var upListSub2 = upList.stream()
        .takeWhile( item -> item.equals("劉能") )
        .collect( Collectors.toList() );
System.out.println( upListSub2 ); // 列印 [劉能]           

檔案讀寫增強

1、Files類增強

我們以前心心念的直接能把檔案内容讀取到String以及String回寫到檔案的功能終于支援了,可以通過Files類的靜态方法writeString()和readString()完成:

Path path = Paths.get("/Users/CodeSheep/test.txt");
String content = Files.readString(path, StandardCharsets.UTF_8);
System.out.println(content);
Files.writeString( path, "王老七", StandardCharsets.UTF_8 );           
2、InputStream增強

InputStream則增加了一個transferTo()方法,直接将資料丢到OutputStream去:

InputStream inputStream = new FileInputStream( "/Users/CodeSheep/test.txt" );
OutputStream outputStream = new FileOutputStream( "/Users/CodeSheep/test2.txt" );
inputStream.transferTo( outputStream );           

支援源檔案直接運作(666!)

比如我寫一個最簡單的Hello World程式:

public class Hello {
    
    public static void main( String[] args ) {
        System.out.println("hello world");
    }
     
}
           

并儲存為hello.java檔案,這時候可以直接用java指令去運作這個Java源檔案,直接省去以前javac編譯源檔案的過程:

java hello.java           
java8 list 轉map_JAVA 8與JAVA 11到底該怎麼選?

怎麼樣?是不是和python源檔案的運作有點像?這個資訊量就有點大了,大家可以自行腦補一下

小結

Java 11确有很多改進,但還是那句話,對于初學者來說Java 8了,沒必要刻意求新,穩才是最重要的

繼續閱讀