日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java 8特性

發(fā)布時(shí)間:2025/7/14 java 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 8特性 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 1.?Java8的新特性
    • 1.1.?Lambda表達(dá)式和函數(shù)式接口
    • 1.2.?接口的默認(rèn)方法和靜態(tài)方法
    • 1.3.?方法引用
  • 2.?Java 8?庫(kù)的新特性
    • 2.1.?Optional
    • 2.2.?Stream
    • 2.3.?日期時(shí)間API(JSR310)
    • 2.4.?Base64
    • 2.5.?并行數(shù)組
    • 2.6.?并發(fā)
  • 3.?新的工具
    • 3.1.?類依賴分析工具:jdeps
  • 4.?JVM的新特性
  • 5. 參考資料

?

正文

回到頂部

1.?Java8的新特性

1.1.?Lambda表達(dá)式和函數(shù)式接口

最簡(jiǎn)單的Lambda表達(dá)式可以用逗號(hào)分隔的參數(shù)列表、->符號(hào)和功能語(yǔ)句塊來(lái)表示。示例如下:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

?請(qǐng)注意到編譯器會(huì)根據(jù)上下文來(lái)推測(cè)參數(shù)的類型,或者你也可以顯示地指定參數(shù)類型,只需要將類型包在括號(hào)里。舉個(gè)例子:

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

?Lambda表達(dá)式可能會(huì)引用類的成員或者局部變量會(huì)被隱式地轉(zhuǎn)變成final類型,下面兩種寫法的效果是一樣的:

String separator = ","; //separator = ";;";//該行編譯時(shí)會(huì)報(bào)錯(cuò):從lambda 表達(dá)式引用的本地變量必須是最終變量或?qū)嶋H上的最終變量 Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );

?和

final String separator = ","; Arrays.asList( "a", "b", "d" ).forEach(( String e ) -> System.out.print( e + separator ) );

?Lambda表達(dá)式可能會(huì)有返回值,編譯器會(huì)根據(jù)上下文推斷返回值的類型。如果lambda的語(yǔ)句塊只有一行,不需要return關(guān)鍵字。下面兩個(gè)寫法是等價(jià)的:

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

?和

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {int result = e1.compareTo( e2 );return result; } );

?Java語(yǔ)言的設(shè)計(jì)者們思考了很多如何讓現(xiàn)有的功能和lambda表達(dá)式友好兼容。于是就有了函數(shù)接口這個(gè)概念。函數(shù)接口是一種只有一個(gè)方法的接口,函數(shù)接口可以隱式地轉(zhuǎn)換成lambda表達(dá)式。

java.lang.Runnable?和java.util.concurrent.Callable是函數(shù)接口兩個(gè)最好的例子。但是在實(shí)踐中,函數(shù)接口是非常脆弱的,只要有人在接口里添加多一個(gè)方法,那么這個(gè)接口就不是函數(shù)接口了,就會(huì)導(dǎo)致編譯失敗。Java 8提供了一個(gè)特殊的注解@FunctionalInterface來(lái)克服上面提到的脆弱性并且顯示地表明函數(shù)接口的目的(java里所有現(xiàn)存的接口都已經(jīng)加上了@FunctionalInterface)。讓我們看看一個(gè)簡(jiǎn)單的函數(shù)接口定義:

@FunctionalInterface public interface Functional {void method(); }

?我們要記住默認(rèn)的方法和靜態(tài)方法(下一節(jié)會(huì)具體解釋)不會(huì)違反函數(shù)接口的約定,例子如下:

@FunctionalInterface public interface FunctionalDefaultMethods {void method();default void defaultMethod() {} }

?函數(shù)式接口的重要屬性是:我們能夠使用lambda實(shí)例化它們。下面是實(shí)例化Runnable函數(shù)式接口的一個(gè)例子。

Runnable r = () ->{ System.out.println("Running!"); }

?新版本向?java.util.function包中添加了很多新的函數(shù)式接口。下面是一些例子:

Function<T, R>——將T作為輸入,返回R作為輸出

Predicate<T>——將T作為輸入,返回一個(gè)布爾值作為輸出

Consumer<T>——將T作為輸入,不返回任何內(nèi)容

Supplier<T>——沒有輸入,返回T

BinaryOperator<T>——將兩個(gè)T作為輸入,返回一個(gè)T作為輸出

?

1.2.?接口的默認(rèn)方法和靜態(tài)方法

Java 8增加了兩個(gè)新的概念在接口聲明的時(shí)候:默認(rèn)和靜態(tài)方法。默認(rèn)方法允許我們?cè)诮涌诶锾砑有碌姆椒?#xff0c;而不會(huì)破壞實(shí)現(xiàn)這個(gè)接口的已有類的兼容性,也就是說不會(huì)強(qiáng)迫實(shí)現(xiàn)接口的類實(shí)現(xiàn)默認(rèn)方法。

默認(rèn)方法和抽象方法的區(qū)別是抽象方法必須要被實(shí)現(xiàn),默認(rèn)方法不是。作為替代方式,接口可以提供一個(gè)默認(rèn)的方法實(shí)現(xiàn),所有這個(gè)接口的實(shí)現(xiàn)類都會(huì)通過繼承得到這個(gè)方法(如果有需要也可以重寫這個(gè)方法),讓我們來(lái)看看下面的例子:

private interface Defaulable {// Interfaces now allow default methods, the implementer may or// may not implement (override) them.default String notRequired() {return "Default implementation";} }private static class DefaultableImpl implements Defaulable {}private static class OverridableImpl implements Defaulable {@Overridepublic String notRequired() {return "Overridden implementation";} }

?接口Defaulable使用default關(guān)鍵字聲明了一個(gè)默認(rèn)方法notRequired(),類DefaultableImpl實(shí)現(xiàn)了Defaulable接口,沒有對(duì)默認(rèn)方法做任何修改。另外一個(gè)類OverridableImpl重寫類默認(rèn)實(shí)現(xiàn),提供了自己的實(shí)現(xiàn)方法。注意,接口不能為Object類中的任何方法提供默認(rèn)的實(shí)現(xiàn)。

Java 8?的另外一個(gè)有意思的新特性是接口里可以聲明靜態(tài)方法,并且可以實(shí)現(xiàn)。例子如下:

private interface DefaulableFactory {// Interfaces now allow static methodsstatic Defaulable create( Supplier< Defaulable > supplier ) {return supplier.get();} }

?下面是把接口的靜態(tài)方法和默認(rèn)方法放在一起的示例(::new?是構(gòu)造方法引用,后面會(huì)有詳細(xì)描述):

public static void main( String[] args ) {Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );System.out.println( defaulable.notRequired() );defaulable = DefaulableFactory.create( OverridableImpl::new );System.out.println( defaulable.notRequired() ); }

?控制臺(tái)的輸出如下:

Default implementation Overridden implementation

??

1.3.?方法引用

方法引用提供了一個(gè)很有用的語(yǔ)義來(lái)直接訪問類或者實(shí)例的已經(jīng)存在的方法或者構(gòu)造方法。結(jié)合Lambda表達(dá)式,方法引用使語(yǔ)法結(jié)構(gòu)緊湊簡(jiǎn)明。不需要復(fù)雜的引用。

下面我們用Car?這個(gè)類來(lái)做示例,Car這個(gè)類有不同的方法定義。讓我們來(lái)看看java 8支持的4種方法引用。

public static class Car {public static Car create( final Supplier< Car > supplier ) {return supplier.get();} public static void collide( final Car car ) {System.out.println( "Collided " + car.toString() );}public void follow( final Car another ) {System.out.println( "Following the " + another.toString() );}public void repair() {System.out.println( "Repaired " + this.toString() );} }

?第一種方法引用是構(gòu)造方法引用,語(yǔ)法是:Class::new?,對(duì)于泛型來(lái)說語(yǔ)法是:Class<T >::new,請(qǐng)注意構(gòu)造方法沒有參數(shù):

final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );

?第二種方法引用是靜態(tài)方法引用,語(yǔ)法是:Class::static_method請(qǐng)注意這個(gè)靜態(tài)方法只支持一個(gè)類型為Car的參數(shù)。

cars.forEach( Car::collide );

?第三種方法引用是類實(shí)例的方法引用,語(yǔ)法是:Class::method請(qǐng)注意方法沒有參數(shù)。

cars.forEach( Car::repair );

?最后一種方法引用是引用特殊類的方法,語(yǔ)法是:instance::method,請(qǐng)注意只接受Car類型的一個(gè)參數(shù)。

final Car police = Car.create( Car::new ); cars.forEach( police::follow );

?運(yùn)行這些例子我們將會(huì)在控制臺(tái)得到如下信息(Car的實(shí)例可能會(huì)不一樣):?

Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d

??

回到頂部

2.?Java 8?庫(kù)的新特性

2.1.?Optional

著名的NullPointerException?是引起系統(tǒng)失敗最常見的原因。很久以前Google Guava項(xiàng)目引入了Optional作為解決空指針異常的一種方式,不贊成代碼被null檢查的代碼污染,期望程序員寫整潔的代碼。受Google Guava的鼓勵(lì),Optional?現(xiàn)在是Java 8庫(kù)的一部分。

Optional?只是一個(gè)容器,它可以保存一些類型的值或者null。它提供很多有用的方法,所以沒有理由顯式地檢查null。

讓我們看看兩個(gè)Optional?用法的小例子:一個(gè)是允許為空的值,另外一個(gè)是不允許為空的值。

Optional< String > fullName = Optional.ofNullable( null ); System.out.println( "Full Name is set? " + fullName.isPresent() ); System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) ); System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );

?如果Optional實(shí)例有非空的值,方法?isPresent()?返回true否則返回false。方法orElseGet提供了回退機(jī)制,當(dāng)Optional的值為空時(shí)接受一個(gè)方法返回默認(rèn)值。map()方法轉(zhuǎn)化Optional當(dāng)前的值并且返回一個(gè)新的Optional實(shí)例。orElse方法和orElseGet類似,但是它不接受一個(gè)方法,而是接受一個(gè)默認(rèn)值。上面代碼運(yùn)行結(jié)果如下:

Full Name is set? false Full Name: [none] Hey Stranger!

?讓我們大概看看另外一個(gè)例子。

Optional< String > firstName = Optional.of( "Tom" ); System.out.println( "First Name is set? " + firstName.isPresent() ); System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) ); System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) ); System.out.println();

?輸出如下:

First Name is set? true First Name: Tom Hey Tom!??

2.2.?Stream

新增加的Stream API?(java.util.stream)引入了在Java里可以工作的函數(shù)式編程。這是目前為止對(duì)java庫(kù)最大的一次功能添加,希望程序員通過編寫有效、整潔和簡(jiǎn)明的代碼,能夠大大提高生產(chǎn)率。

list轉(zhuǎn)map

?

常用方式

?

public Map<Long, String> getIdNameMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsername)); }

?

?

收集成實(shí)體本身map

?

public Map<Long, Account> getIdAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, account -> account)); }

?

?

account -> account是一個(gè)返回本身的lambda表達(dá)式,其實(shí)還可以使用Function接口中的一個(gè)默認(rèn)方法代替,使整個(gè)方法更簡(jiǎn)潔優(yōu)雅:

?

public Map<Long, Account> getIdAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, Function.identity())); }

?

?

重復(fù)key的情況

?

代碼如下:

?

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity())); }

?

?

這個(gè)方法可能報(bào)錯(cuò)(java.lang.IllegalStateException: Duplicate key),因?yàn)閚ame是有可能重復(fù)的。toMap有個(gè)重載方法,可以傳入一個(gè)合并的函數(shù)來(lái)解決key沖突問題:

?

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2)); }

?

?

這里只是簡(jiǎn)單的使用后者覆蓋前者來(lái)解決key重復(fù)問題。

?

指定具體收集的map

?

toMap還有另一個(gè)重載方法,可以指定一個(gè)Map的具體實(shí)現(xiàn),來(lái)收集數(shù)據(jù):

?

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2, LinkedHashMap::new)); }

?

?

?

Stream API讓集合處理簡(jiǎn)化了很多(我們后面會(huì)看到不僅限于Java集合類)。讓我們從一個(gè)簡(jiǎn)單的類Task開始來(lái)看看Stream的用法。

public class Streams {private enum Status {OPEN, CLOSED};private static final class Task {private final Status status;private final Integer points;Task( final Status status, final Integer points ) {this.status = status;this.points = points;}public Integer getPoints() {return points;}public Status getStatus() {return status;}@Overridepublic String toString() {return String.format( "[%s, %d]", status, points );} } }

?Task類有一個(gè)分?jǐn)?shù)的概念(或者說是偽復(fù)雜度),其次是還有一個(gè)值可以為OPEN或CLOSED的狀態(tài).讓我們引入一個(gè)Task的小集合作為演示例子:

final Collection< Task > tasks = Arrays.asList(new Task( Status.OPEN, 5 ),new Task( Status.OPEN, 13 ),new Task( Status.CLOSED, 8 ) );

?第一個(gè)問題是所有的開放的Task的點(diǎn)數(shù)是多少?在java 8?之前,通常的做法是用foreach迭代。但是Java8里頭我們會(huì)用Stream。Stream是多個(gè)元素的序列,支持串行和并行操作。

// Calculate total points of all active tasks using sum() final long totalPointsOfOpenTasks = tasks.stream().filter( task -> task.getStatus() == Status.OPEN ).mapToInt( Task::getPoints ).sum(); System.out.println( "Total points: " + totalPointsOfOpenTasks );

?控制臺(tái)的輸出將會(huì)是:

Total points: 18

?上面代碼執(zhí)行的流程是這樣的,首先Task集合會(huì)被轉(zhuǎn)化為Stream表示,然后filter操作會(huì)過濾掉所有關(guān)閉的Task,接下來(lái)使用Task::getPoints?方法取得每個(gè)Task實(shí)例的點(diǎn)數(shù),mapToInt方法會(huì)把Task Stream轉(zhuǎn)換成Integer Stream,最后使用Sum方法將所有的點(diǎn)數(shù)加起來(lái)得到最終的結(jié)果。

在我們看下一個(gè)例子之前,我們要記住一些關(guān)于Stream的說明。Stream操作被分為中間操作和終點(diǎn)操作。

中間操作返回一個(gè)新的Stream。這些中間操作是延遲的,執(zhí)行一個(gè)中間操作比如filter實(shí)際上不會(huì)真的做過濾操作,而是創(chuàng)建一個(gè)新的Stream,當(dāng)這個(gè)新的Stream被遍歷的時(shí)候,它里頭會(huì)包含有原來(lái)Stream里符合過濾條件的元素。

終點(diǎn)操作比如說forEach或者sum會(huì)遍歷Stream從而產(chǎn)生最終結(jié)果或附帶結(jié)果。終點(diǎn)操作執(zhí)行完之后,Stream管道就被消費(fèi)完了,不再可用。在幾乎所有的情況下,終點(diǎn)操作都是即時(shí)完成對(duì)數(shù)據(jù)的遍歷操作。

Stream的另外一個(gè)價(jià)值是Stream創(chuàng)造性地支持并行處理。讓我們看看下面這個(gè)例子,這個(gè)例子把所有task的點(diǎn)數(shù)加起來(lái)。

// Calculate total points of all tasks final double totalPoints = tasks.stream().parallel().map( task -> task.getPoints() ) // or map( Task::getPoints ).reduce( 0, Integer::sum ); System.out.println( "Total points (all tasks): " + totalPoints );

?這個(gè)例子跟上面那個(gè)非常像,除了這個(gè)例子里使用了parallel()方法???????并且計(jì)算最終結(jié)果的時(shí)候使用了reduce方法。

輸出如下:

Total points (all tasks): 26.0

?經(jīng)常會(huì)有這個(gè)一個(gè)需求:我們需要按照某種準(zhǔn)則來(lái)對(duì)集合中的元素進(jìn)行分組。Stream也可以處理這樣的需求,下面是一個(gè)例子:

// Group tasks by their status final Map< Status, List< Task > > map = tasks.stream().collect( Collectors.groupingBy( Task::getStatus ) ); System.out.println( map );

?控制臺(tái)的輸出如下:

{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}

按照某種準(zhǔn)則來(lái)對(duì)集合中的元素進(jìn)行分組并統(tǒng)計(jì)每組個(gè)數(shù):

// Group tasks by their status final Map< Status, Long > map = tasks.stream().collect( Collectors.groupingBy( Task::getStatus, Collectors.counting()) );
System.out.println( map );

?按照某種準(zhǔn)則來(lái)對(duì)集合中的元素進(jìn)行分組并統(tǒng)計(jì)每組里某個(gè)字段的平均值:?

// Group tasks by their status final Map< Status, Long > map = tasks.stream().collect( Collectors.groupingBy( Task::getStatus, Collectors.averagingInt(Task::getPoints)) );
System.out.println( map );

?讓我們來(lái)計(jì)算整個(gè)集合中每個(gè)task分?jǐn)?shù)(或權(quán)重)的平均值來(lái)結(jié)束task的例子。

// Calculate the weight of each tasks (as percent of total points) final Collection< String > result = tasks.stream() // Stream< String >.mapToInt( Task::getPoints ) // IntStream.asLongStream() // LongStream.mapToDouble( points -> points / totalPoints ) // DoubleStream.boxed() // Stream< Double >.mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream.mapToObj( percentage -> percentage + "%" ) // Stream< String>.collect( Collectors.toList() ); // List< String > System.out.println( result );

?控制臺(tái)輸出如下:

[19%, 50%, 30%]

?最后,就像前面提到的,Stream API不僅僅處理Java集合框架。像從文本文件中逐行讀取數(shù)據(jù)這樣典型的I/O操作也很適合用Stream API來(lái)處理。下面用一個(gè)例子來(lái)應(yīng)證這一點(diǎn)。

final Path path = new File( filename ).toPath(); try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println ); }

?Stream的方法onClose?返回一個(gè)等價(jià)的有額外句柄的Stream,當(dāng)Stream的close()方法被調(diào)用的時(shí)候這個(gè)句柄會(huì)被執(zhí)行。

流可以是無(wú)限的、有狀態(tài)的,可以是順序的,也可以是并行的。在使用流的時(shí)候,你首先需要從一些來(lái)源中獲取一個(gè)流,執(zhí)行一個(gè)或者多個(gè)中間操作,然后執(zhí)行一個(gè)最終操作。中間操作包括filter、map、flatMap、peel、distinct、sorted、limit和substream。終止操作包括forEach、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst和findAny。?java.util.stream.Collectors是一個(gè)非常有用的實(shí)用類。該類實(shí)現(xiàn)了很多歸約操作,例如將流轉(zhuǎn)換成集合和聚合元素。

?Stream有串行和并行兩種,串行Stream上的操作是在一個(gè)線程中依次完成,而并行Stream則是在多個(gè)線程上同時(shí)執(zhí)行。

?下面的例子展示了是如何通過并行Stream來(lái)提升性能:

?首先我們創(chuàng)建一個(gè)沒有重復(fù)元素的大表:

int max = 1000000; List<String> values = new ArrayList<>(max); for (int i = 0; i < max; i++) {UUID uuid = UUID.randomUUID();values.add(uuid.toString()); }

?然后我們計(jì)算一下排序這個(gè)Stream要耗時(shí)多久,

串行排序:

long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); // 串行耗時(shí): 899 ms

?并行排序:

long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); // 并行排序耗時(shí): 472 ms

?上面兩個(gè)代碼幾乎是一樣的,但是并行版的快了50%之多,唯一需要做的改動(dòng)就是將stream()改為parallelStream()。

??

2.3.?日期時(shí)間API(JSR310)

新的java.time包包含了所有關(guān)于日期、時(shí)間、日期時(shí)間、時(shí)區(qū)、Instant(跟日期類似但精確到納秒)、duration(持續(xù)時(shí)間)和時(shí)鐘操作的類。設(shè)計(jì)這些API的時(shí)候很認(rèn)真地考慮了這些類的不變性(從java.util.Calendar吸取的痛苦教訓(xùn))。如果需要修改時(shí)間對(duì)象,會(huì)返回一個(gè)新的實(shí)例。

  • Clock

Clock使用時(shí)區(qū)來(lái)訪問當(dāng)前的instant, date和time。Clock類可以替換?System.currentTimeMillis()?和?TimeZone.getDefault().

  • LocalDate

LocalDate只保存有ISO-8601日期系統(tǒng)的日期部分,有時(shí)區(qū)信息

  • LocalTime

LocalTime只保存ISO-8601日期系統(tǒng)的時(shí)間部分,沒有時(shí)區(qū)信息。

  • LocalDateTime

LocalDateTime類合并了LocalDate和LocalTime,它保存有ISO-8601日期系統(tǒng)的日期和時(shí)間,但是沒有時(shí)區(qū)信息。

  • ZonedDateTime

如果您需要一個(gè)類持有日期時(shí)間和時(shí)區(qū)信息,可以使用ZonedDateTime,它保存有ISO-8601日期系統(tǒng)的日期和時(shí)間,而且有時(shí)區(qū)信息。

  • Duration

Duration持有的時(shí)間精確到納秒。它讓我們很容易計(jì)算兩個(gè)日期中間的差異。

2.4.?Base64

對(duì)Base64的支持最終成了Java 8標(biāo)準(zhǔn)庫(kù)的一部分,非常簡(jiǎn)單易用:

package com.javacodegeeks.java8.base64;import java.nio.charset.StandardCharsets; import java.util.Base64; public class Base64s { public static void main(String[] args) { final String text = "Base64 finally in Java 8!"; final String encoded = Base64 .getEncoder() .encodeToString( text.getBytes( StandardCharsets.UTF_8 ) ); System.out.println( encoded ); final String decoded = new String( Base64.getDecoder().decode( encoded ), StandardCharsets.UTF_8 ); System.out.println( decoded ); } }

?控制臺(tái)輸出的編碼和解碼的字符串:

QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ== Base64 finally in Java 8!

?新的Base64API也支持URL和MINE的編碼解碼:

(Base64.getUrlEncoder()?/?Base64.getUrlDecoder(),?Base64.getMimeEncoder()?/?Base64.getMimeDecoder()).

?

2.5.?并行數(shù)組

Java 8新增加了很多方法支持并行的數(shù)組處理。最重要的大概是parallelSort()這個(gè)方法顯著地使排序在多核計(jì)算機(jī)上速度加快。下面的小例子演示了這個(gè)新的方法(parallelXXX)的行為。

import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; public class ParallelArrays {public static void main( String[] args ) {long[] arrayOfLong = new long [ 20000 ];Arrays.parallelSetAll( arrayOfLong,index -> ThreadLocalRandom.current().nextInt( 1000000 ) );Arrays.stream( arrayOfLong ).limit( 10 ).forEach(i -> System.out.print( i + " " ) );System.out.println();Arrays.parallelSort( arrayOfLong );Arrays.stream( arrayOfLong ).limit( 10 ).forEach(i -> System.out.print( i + " " ) );System.out.println();} }

?這一小段代碼使用parallelSetAll()?方法填充這個(gè)長(zhǎng)度是2000的數(shù)組,然后使用parallelSort()?排序。這個(gè)程序輸出了排序前和排序后的10個(gè)數(shù)字來(lái)驗(yàn)證數(shù)組真的已經(jīng)被排序了。示例可能的輸出如下(請(qǐng)注意這些數(shù)字是隨機(jī)產(chǎn)生的)

Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378
Sorted: 39 220 263 268 325 607 655 678 723 793

?

2.6.?并發(fā)

在新增Stream機(jī)制與lambda的基礎(chǔ)之上,在java.util.concurrent.ConcurrentHashMap中加入了一些新方法來(lái)支持聚集操作。同時(shí)也在java.util.concurrent.ForkJoinPool類中加入了一些新方法來(lái)支持共有資源池(common pool)。

新增的java.util.concurrent.locks.StampedLock類提供一直基于容量的鎖,這種鎖有三個(gè)模型來(lái)控制讀寫操作(它被認(rèn)為是不太有名的java.util.concurrent.locks.ReadWriteLock類的替代者)。

在java.util.concurrent.atomic包中還增加了下面這些類:

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder
  • ?

    回到頂部

    3.?新的工具

    3.1.?類依賴分析工具:jdeps

    Jdeps是一個(gè)功能強(qiáng)大的命令行工具,它可以幫我們顯示出包層級(jí)或者類層級(jí)java類文件的依賴關(guān)系。它接受class文件、目錄、jar文件作為輸入,默認(rèn)情況下,jdeps會(huì)輸出到控制臺(tái)。

    作為例子,讓我們看看現(xiàn)在很流行的Spring框架的庫(kù)的依賴關(guān)系報(bào)告。為了讓報(bào)告短一些,我們只分析一個(gè)jar:?org.springframework.core-3.0.5.RELEASE.jar.

    jdeps org.springframework.core-3.0.5.RELEASE.jar?這個(gè)命令輸出內(nèi)容很多,我們只看其中的一部分,這些依賴關(guān)系根絕包來(lái)分組,如果依賴關(guān)系在classpath里找不到,就會(huì)顯示not found.

    ??

    回到頂部

    4.?JVM的新特性

    JVM內(nèi)存永久區(qū)已經(jīng)被metaspace替換(JEP 122)。JVM參數(shù)?-XX:PermSize?和?–XX:MaxPermSizeXX:MetaSpaceSize?和?-XX:MaxMetaspaceSize代替

    ??

    回到頂部

    5. 參考資料

    http://ifeve.com/java-8-features-tutorial/

    https://blog.chou.it/2014/03/java-8-new-features/

    http://www.infoq.com/cn/news/2013/08/everything-about-java-8#

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

    分類:?java基礎(chǔ)

    轉(zhuǎn)載于:https://www.cnblogs.com/DreamRecorder/p/9203399.html

    總結(jié)

    以上是生活随笔為你收集整理的Java 8特性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。