java8 list 行转列_Java14 都来了,你还不会用 Java8吗?
Java 8 于2014年3月18日發布,并且成為主流的 Java,如今,雖然 Java 14 都已經發布了,但是 開發者和公司選擇的版本依舊是經久不衰的 Java 8 版本,如果你還不了解這些新特性,是時候學習一下了。
Java 8 更新的一些重要功能一覽
- Iterable 接口中的 forEach() 方法
- 接口中的默認方法和靜態方法
- 功能接口和 Lambda 表達式
- 用于集合上批量數據操作的 Java Stream API
- Java 時間 API
- 集合 API 的改進
- 并發 API 改進
- Java IO改進
- 其他核心 API 改進
下面來簡要了解一下這些Java 8功能。我將提供一些代碼片段以更好地理解,因此,如果要在Java 8中運行程序,則必須按照以下步驟設置Java 8環境。
下載并安裝JDK8。像其他Java版本一樣,安裝也很簡單,運行下面的示例,必須要安裝 JDK 環境。
下載最新的 IDEA 開發環境,這里我不推薦使用 Eclipse ,但是如果你有使用 Eclipse 習慣,那我在這里推薦你可以嘗試 IDEA,因為它真的太棒啦~
Iterable 接口中的 forEach()方法
在 Java 8 以前,每當需要遍歷 Collection 時,就需要創建一個 Iterator 來進行迭代 Collection 對象,然后針對 Collection 中 的每個元素將業務邏輯循環在一起。如果迭代器使用不正確,可能會拋出 ConcurrentModificationException。
Java 8 在接口中引入了forEach方法,java.lang.Iterable因此在編寫代碼時,我們僅關注業務邏輯。forEach方法將java.util.function.Consumer對象作為參數,因此有助于將我們的業務邏輯放在一個可以重用的單獨位置。讓我們通過簡單的示例查看forEach用法。
package?com.journaldev.java8.foreach;import?java.util.ArrayList;import?java.util.Iterator;import?java.util.List;import?java.util.function.Consumer;import?java.lang.Integer;public?class?Java8ForEachExample?{????public?static?void?main(String[]?args)?{????????//creating?sample?Collection????????List?myList?=?new?ArrayList();????????for(int?i=0;?i<10;?i++)?myList.add(i);????????//traversing?using?Iterator????????Iterator?it?=?myList.iterator();????????while(it.hasNext()){????????????Integer?i?=?it.next();????????????System.out.println("Iterator?Value::"+i);????????}????????//traversing?through?forEach?method?of?Iterable?with?anonymous?class????????myList.forEach(new?Consumer()?{????????????public?void?accept(Integer?t)?{????????????????System.out.println("forEach?anonymous?class?Value::"+t);????????????}????????});????????//traversing?with?Consumer?interface?implementation????????MyConsumer?action?=?new?MyConsumer();????????myList.forEach(action);????}}//Consumer?implementation?that?can?be?reusedclass?MyConsumer?implements?Consumer{????public?void?accept(Integer?t)?{????????System.out.println("Consumer?impl?Value::"+t);????}}代碼的行數可能會增加,但是forEach方法有助于將迭代邏輯和業務邏輯放在不同的位置,從而使關注點和代碼更清晰地分離。
接口中的默認方法和靜態方法
如果仔細閱讀forEach方法的詳細信息,會注意到它是在Iterable接口中定義的,但我們知道接口不能具有方法主體。從Java 8開始,接口已增強為具有實現的方法。我們可以使用default和static關鍵字來創建帶有方法實現的接口。Iterable接口中的forEach方法實現為:
default?void?forEach(Consumer?super?T>?action)?{????Objects.requireNonNull(action);????for?(T?t?:?this)?{????????action.accept(t);????}}我們知道Java不會在Class中提供多重繼承,因為它會導致Diamond問題。由于接口現在類似于抽象類,因此現在如何使用接口處理它。解決方案是在這種情況下編譯器將引發異常,我們將不得不在實現接口的類中提供實現邏輯。
package?com.journaldev.java8.defaultmethod;@FunctionalInterfacepublic?interface?Interface1?{????void?method1(String?str);????default?void?log(String?str){????????System.out.println("I1?logging::"+str);????}????static?void?print(String?str){????????System.out.println("Printing?"+str);????}????//trying?to?override?Object?method?gives?compile-time?error?as????//"A?default?method?cannot?override?a?method?from?java.lang.Object"//????default?String?toString(){//????????return?"i1";//????}}package?com.journaldev.java8.defaultmethod;@FunctionalInterfacepublic?interface?Interface2?{????void?method2();????default?void?log(String?str){????????System.out.println("I2?logging::"+str);????}}注意,兩個接口都有一個帶有實現邏輯的通用方法log()。
package?com.journaldev.java8.defaultmethod;public?class?MyClass?implements?Interface1,?Interface2?{????@Override????public?void?method2()?{????}????@Override????public?void?method1(String?str)?{????}????//MyClass?won't?compile?without?having?it's?own?log()?implementation????@Override????public?void?log(String?str){????????System.out.println("MyClass?logging::"+str);????????Interface1.print("abc");????}}如你所見, Interface1 具有在 MyClass.log() 方法實現中使用的靜態方法實現。Java 8 在 Collection API 中大量使用默認和靜態方法,并且添加了默認方法,以便使 JDK 8 之前的代碼保持向后兼容。
如果層次結構中的任何類都具有具有相同的方法,則默認方法將變得無關緊要。由于任何實現接口的類都已經具有 Object 作為超類,因此如果接口中具有 equals(),hashCode() 默認方法,它將變得無關緊要。這就是為什么為了更清楚起見,不允許接口具有Object默認方法。
有關Java 8接口特性的完整詳細信息,請閱讀 Java 8接口更改。
功能接口和Lambda表達式
如果你注意到上述接口代碼,則會注意到 @FunctionalInterface 注解。該功能接口是Java 8 中引入的新概念。具有一種抽象方法的接口就變成了功能接口。我們不需要使用 @FunctionalInterface 注解將接口標記為Functional Interface。@FunctionalInterface 注解是一種避免在功能接口中意外添加抽象方法的工具。您可以將其視為 @Override 批注,并且是使用它的最佳實踐。java.lang.Runnable 使用單個抽象方法 run() 是功能接口的一個很好的例子。
功能接口的主要優點之一是可以使用 lambda 表達式實例化它們。在 Java 8 之前,可以用匿名類實例化一個接口,但是代碼看起來很龐大。
Runnable?r?=?new?Runnable(){????@Override????public?void?run()?{????????????System.out.println("My?Runnable");????}};由于功能接口只有一種方法,因此 lambda 表達式可以輕松提供該方法的實現。只需要提供方法參數和業務邏輯。例如,可以使用 lambda 表達式編寫上面的實現:
Runnable?r1?=?()?->?{????????????System.out.println("My?Runnable");????????};如果方法實現中只有一條語句,那么我們也不需要花括號。例如,上面的Interface1匿名類可以使用lambda實例化,如下所示:
Interface1?i1?=?(s)?->?System.out.println(s);i1.method1("abc");因此,lambda 表達式是輕松創建功能接口的匿名類的一種方法。使用 lambda 表達式對于代碼運行沒有任何的影響,因此要謹慎謹慎使用它,因為我們并不介意編寫一些額外的代碼行。
新包裝 java.util.function 添加了帶有功能接口束的,以提供 lambda 表達式和方法引用的目標類型。Lambda 表達式是一個非常復雜的話題,后續我會編寫一篇文章專門針對 lambda 表達式。
您可以在 Java 8 Lambda Expressions Tutorial 中閱讀完整的教程。
用于集合上批量數據操作的Java Stream API
java.util.stream 是Java 8中添加的一個新內容,以對該集合執行類似過濾/映射/遍歷的操作。Stream API 將允許順序執行和并行執行。這對我來說是非常好用的一個功能,因為我經常處理 Collections,而且通常使用很多的數據進行過濾數據,遍歷數據,stream 就完美的解決了這個問題。
Collection 接口已使用 stream() 和 parallelStream() 默認方法進行了擴展,以獲取用于順序執行和并行執行的 Stream ,用一個簡單的例子看看它們的用法。
package?com.journaldev.java8.stream;import?java.util.ArrayList;import?java.util.List;import?java.util.stream.Stream;public?class?StreamExample?{????public?static?void?main(String[]?args)?{????????List?myList?=?new?ArrayList<>();????????for(int?i=0;?i<100;?i++)?myList.add(i);????????//sequential?stream????????Stream?sequentialStream?=?myList.stream();????????//parallel?stream????????Stream?parallelStream?=?myList.parallelStream();????????//using?lambda?with?Stream?API,?filter?example????????Stream?highNums?=?parallelStream.filter(p?->?p?>?90);????????//using?lambda?in?forEach????????highNums.forEach(p?->?System.out.println("High?Nums?parallel="+p));????????Stream?highNumsSeq?=?sequentialStream.filter(p?->?p?>?90);????????highNumsSeq.forEach(p?->?System.out.println("High?Nums?sequential="+p));????}}如果你運行示例代碼,將獲得如下輸出:
High?Nums?parallel=91High?Nums?parallel=96High?Nums?parallel=93High?Nums?parallel=98High?Nums?parallel=94High?Nums?parallel=95High?Nums?parallel=97High?Nums?parallel=92High?Nums?parallel=99High?Nums?sequential=91High?Nums?sequential=92High?Nums?sequential=93High?Nums?sequential=94High?Nums?sequential=95High?Nums?sequential=96High?Nums?sequential=97High?Nums?sequential=98High?Nums?sequential=99請注意,并行處理的時候。值不按順序排列,因此在處理龐大的集合時,并行處理將非常有幫助。
這篇文章無法涵蓋有關Stream API的所有內容,您可以在 Java 8 Stream API Example Tutorial 中閱讀有關Stream API的所有內容。
Java 8 時間API
在之前的 Java 中使用日期,時間和時區一直很困難。Java 中沒有用于日期和時間的標準方法或 API。Java 8 有一個不錯的附加功能是 java.time 軟件包,它簡化了 Java 中使用時間的過程。
僅查看 Java Time API 軟件包,就可以感覺到它非常易于使用。它具有一些子包 java.time.format,這些子包提供用于打印和解析日期和時間的類,還有java.time.zone 提供對時區及其規則的支持。
新的 Time API 在整月的幾個月和一周中的幾天中都使用了枚舉而不是整數常量。常用的類之一是 DateTimeFormatter 將 DateTime 對象轉換為字符串。
有關完整的教程,請轉到 Java日期時間API示例教程。
集合API的改進
在上面的介紹已經看到了 forEach() 方法和用于集合的 Stream API。
Collection API 中添加的一些新方法是:
IteratorforEachRemaining(Consumer action) 在所有元素都已處理完畢或該動作引發異常之前,對其余每個元素執行給定操作的默認方法。
CollectionremoveIf(Predicate filter) 刪除此集合中所有滿足給定謂詞的元素的默認方法。
Collection spliterator() 該方法返回Spliterator實例,該實例可用于順序或并行遍歷元素。地圖replaceAll(),compute(),merge()方法。
另外還有一些具有 hash 沖突 的HashMap 類的性能改進
并發API改進
一些重要的并發API增強功能包括:
ConcurrentHashMap compute(),forEach(),forEachEntry(),forEachKey(),forEachValue(),merge(),reduce()和search()方法。CompletableFuture 可以明確完成(設置其值和狀態)。Executors newWorkStealingPool() 使用所有可用處理器作為目標并行度級別創建竊取線程池的方法。
Java IO改進
我知道的一些IO改進:
Files.list(Path dir) 返回一個延遲加載的 Stream,其元素是目錄中的文件夾和文件列表。
Files.lines(Path path) 返回一個讀取指定文件所有行的文件流。
Files.find() 返回一個根據指定目錄搜索指定文件的文件列表流。
BufferedReader.lines() 返回一個Stream,其元素是從此 BufferedReader 中讀取的行。
其他核心API改進
一些雜項API改進在某些特殊情況可能會派上用場:
- ThreadLocal 靜態方法可以使用 withInitial 方法創建實例。
- 比較器接口已擴展了許多默認和靜態方法,用于自然排序,反向排序等。
- Integer,Long 和 Double 包裝器類中增加了 min(),max() 和 sum() 方法。
- Boolean 類中的 logicalAnd() ,logicalOr() 和 logicalXor() 方法。
- ZipFile.stream() 方法獲取 ZIP 文件條目上的有序Stream,并以壓縮時的順序出現在 Stream 中。
- Math 類中增加了幾種實用方法。
- jjs 添加命令以調用 Nashorn Engine。
- jdeps 添加命令以分析類文件
- JDBC-ODBC 橋已被刪除。
- PermGen 內存空間已被刪除
碼字不易,如果能幫到你,請點點關注~
總結
以上是生活随笔為你收集整理的java8 list 行转列_Java14 都来了,你还不会用 Java8吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 早报:荣耀Magic5系列新机入网 美国
- 下一篇: 全球第一次!DDR5内存加上一颗特殊芯片