久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java 11 中 11 個(gè)不為人知的瑰寶

 昵稱(chēng)10087950 2022-07-26 發(fā)布于江蘇

 

我們已經(jīng)迎來(lái)了 Java 11,,盡管它的升級(jí)介紹里沒(méi)有什么跨時(shí)代的特性,,但卻有一些不為人知的瑰寶,像沙礫中的鉆石一般,。

 

當(dāng)然,,你肯定了解到了一些特性,比如說(shuō)響應(yīng)式的 HTTP/2 的 API ,,不需要編譯就可以直接運(yùn)行源代碼等,。

 

但是,你是否有去嘗試過(guò) String ,、Optional,、Collection 等常用類(lèi)的擴(kuò)展,如果還沒(méi)有,,那么恭喜你,,你將從本文中了解到 Java 11 不為人知的 11 個(gè)像鉆石般寶貴的知識(shí)點(diǎn)。

 

01

 

Lambda 表達(dá)式的參數(shù)類(lèi)型推斷

 

當(dāng)我們?cè)趯?xiě) Lambda 表達(dá)式時(shí),,你可以指定具體類(lèi)型,,或者直接省略它:

 

ction append = string -> string + " ";

 

Function append = (String s) -> s + " ";

 

在 Java 10 中添加了一個(gè) var 關(guān)鍵字,但是你并不能在 Lambda 表達(dá)示中使用:

 

// compile error in Java 10

 

Function append = (var string) -> string + " ";

 

然而,我們?cè)?nbsp;Java 11 中卻可以,。來(lái)思考一下,,為什么可以如此使用?它不僅僅是在省略類(lèi)型的變量前面加一個(gè) var ,,在這種寫(xiě)法中,,有以下兩個(gè)新的特性:

l  通過(guò)去除特殊情況,使 var 變得更加統(tǒng)一,;

l  允許在 Lambda 的參數(shù)上添加注解,,而不需要寫(xiě)上完整的變量類(lèi)型名稱(chēng)。

舉個(gè)例子,,來(lái)看一下這兩點(diǎn):

 

List> types = /*...*/;

 

types.stream()

 

// this is fine, but we need @Nonnull on the type

 

    .filter(type -> check(type))

 

// in Java 10, we need to do this ~> ugh!

 

    .filter((@Nonnull EnterpriseGradeType type) -> check(type))

 

// in Java 11, we can do this ~> better

 

    .filter((@Nonnull var type) -> check(type))

 

我們可以在 Lambda 表達(dá)式中同時(shí)使用清晰的,、不明確的 、var 聲明的變量,,像如下代碼:

 

 (var type, String option, index) -> ...

 

雖然也可以這樣實(shí)現(xiàn),,但是它會(huì)讓代碼看起來(lái)很復(fù)雜。因此,,筆者建議選取其中一種方式并堅(jiān)持使用下去,。只是為了其中一個(gè)參數(shù)可添加注解,讓所有的參數(shù)都加上 var ,,這樣做的確有點(diǎn)煩人,,但筆者認(rèn)為這是可以忍受的。

 

02

 

"String::lines" 獲取數(shù)據(jù)行數(shù)

 

你有一個(gè)多行的字符串,,想要對(duì)每一行進(jìn)行單獨(dú)操作,,你可以使用 String::lines 來(lái)實(shí)現(xiàn):

 

var multiline = "Thisis amultilinestring";

 

multiline.lines()

 

// we now have a `Stream`

 

    .map(line -> "http:// " + line)

 

    .forEach(System.out::println);

 

// OUTPUT:

 

// This

 

// is a

 

// multiline

 

// string

 

上面例子中的字符串中的換行使用的是 Windows 中的 。盡管我是在 Linux 中使用,, lines() 依然可以拆分他們,。

 

在不同的操作系統(tǒng)中,lines() 這個(gè)方法都會(huì)把 ,, ,, 作為終止符。即使我們?cè)?nbsp;string 中混合使用他們,。

 

數(shù)據(jù)行里面不包含終止符自己,但是可以為空("likein thiscase" ,,它有五行),,如果終止符在字符串末尾,lines() 方法會(huì)忽略掉它(likehere ; 只有兩行)

 

與 split("R") 不同,, lines() 是惰性的,。

 

使用更快的搜索方式來(lái)搜索新的終止符以提高性能。

 

如果有人使用 JMH 來(lái)驗(yàn)證這一點(diǎn),請(qǐng)告訴我結(jié)果,。

 

不僅如此,,它可以更好的傳達(dá)意思并返回更方便的數(shù)據(jù)結(jié)構(gòu)(不是數(shù)組,而是流),。

 

03

 

使用"String::strip"來(lái)移除空格

 

一直以來(lái),,String 使用 trim 來(lái)移除空白字符,此方法認(rèn)為所有的內(nèi)容都是使用了大于 U+0020 的 Unicode 值,。BACKSPACE (U+0008) 是空白,,BELL (U+0007) 也是,但是換行符(U+2028) 不是空白字符,。

 

Java 11 引入了 strip ,,它與 trim 有一些細(xì)微的差別,它使用 Java 5 中的 "Character::isWhitespace" 來(lái)識(shí)別要移除的內(nèi)容,。它的文檔如下:

l  SPACESEPARATOR, LINESEPARATOR, PARAGRAPH_SEPARATOR, but not non-breaking space

l  HORIZONTAL TABULATION (U+0009), LINE FEED (U+000A), VERTICAL TABULATION (U+000B), FORM FEED (U+000C), CARRIAGE RETURN (U+000D)

l  FILE SEPARATOR (U+001C), GROUP SEPARATOR (U+001D), RECORD SEPARATOR(U+001E), UNIT SEPARATOR (U+001F)

基于此邏輯,,這兒還有兩個(gè)移除方法: stripLeading 、stripTailing ,,你按照你自己想要的結(jié)果來(lái)選擇對(duì)應(yīng)的方法,。

 

最后,如果你需要知到去掉空白字符后,,是否為空,,你不需要執(zhí)行 strip 操作,只需要使用 isBlank 來(lái)判斷:

 

" ".isBlank()); // space ~> true

 

" abc ".isBlank()); // non-breaking space ~> false

 

04

 

使用“String::repeat” 來(lái)復(fù)制字符串

 

生活大妙招:

l  第一步:深入了解 JDK 的發(fā)展與變更

 

JDK 文檔

l  第二步:在 StackOverflow 搜索相關(guān)問(wèn)題的答案

 

StackOverflow 結(jié)果

l  第三步:根據(jù)即將到來(lái)的變更去回復(fù)對(duì)應(yīng)的答案

 

回答答案

l  第四步:

ˉ_(ツ)_/ˉ

l  第五步:

174407245CF9496B82F9259C100E52BA.gif

如你所見(jiàn),, String 現(xiàn)在有一個(gè) repeat(int) 的方法,。毋庸置疑,它的行為和我們理解的一模一樣,,完全沒(méi)有可以爭(zhēng)議的地方,。

 

05 

 

使用"Path::of"來(lái)創(chuàng)建路徑

 

我非常喜歡 Path 這個(gè) API,它解決了我們?cè)诼窂?nbsp;,、URI ,、URL 、FILE 來(lái)回切換的麻煩問(wèn)題,。在 Java 11 中,,我們可以使用 Paths::get 和 Path::of 來(lái)讓它們變得很統(tǒng)一:

 

Path tmp = Path.of("/home/nipa""tmp");

 

Path codefx = Path.of(URI.create("http://"));

 

這兩個(gè)方法,被作為標(biāo)準(zhǔn)方法來(lái)使用,。

 

06

 

使用 'Files::readString’ 和 'Files::writeString’ 來(lái)進(jìn)行文件讀寫(xiě)

 

如果你需要從一個(gè)非常大的文件里面讀取內(nèi)容,,我一般使用 Files::lines ,他返回一個(gè)惰性數(shù)據(jù)流,。同樣,,如果要將不可能同時(shí)出來(lái)在內(nèi)容存儲(chǔ)在文件里,,我一般通過(guò)傳遞一個(gè) Interable 來(lái)使用 Files::write 寫(xiě)到文件中。

 

但是我要如何很方便的處理一個(gè)簡(jiǎn)單的字符串呢,?使用 Files::readAllBytes 和 Files::write 并不是特別方便,, 因?yàn)檫@兩個(gè)方法都只能處理 byte 數(shù)組。

 

在 Java 11 中給 Files 添加了 readString ,、writeString 兩個(gè)方法:

 

String haiku = Files.readString(Path.of("haiku.txt"));

 

String modified = modify(haiku);

 

Files.writeString(Path.of("haiku-mod.txt"), modified);

 

簡(jiǎn)單易用,,當(dāng)然,如果你有需要,,你也可以將字符數(shù)組傳底給 readString 方法,,你也可以給 writeString 指定文件打開(kāi)方式。

 

07

 

使用"Reader::nullReader"來(lái)處理空的 I/O 操作

 

你需要一個(gè)不處理輸入數(shù)據(jù)的 OutputStream 時(shí),,你要怎么處理,?那一個(gè)空的 InputStream 呢?Reader,、Writer 呢,?

 

在 Java 11 中,你可以做如下轉(zhuǎn)換:

 

InputStream input = InputStream.nullInputStream();

 

OutputStream output = OutputStream.nullOutputStream();

 

Reader reader = Reader.nullReader();

 

Writer writer = Writer.nullWriter();

 

但我并不認(rèn)為 null 是一個(gè)好的前綴,, 我不喜歡這種意圖不明確的定義,。或許使用 NOOP 更好,。

 

08

 

使用"Collection::toArray"將集合轉(zhuǎn)成數(shù)組

 

你是如何將集合轉(zhuǎn)成數(shù)組的,?

 

// 在 Java 11 之前的版本

 

List list = /*...*/;

 

Object[] objects = list.toArray();

 

String[] strings_0 = list.toArray(new String[0]);

 

String[] strings_size = list.toArray(new String[list.size()])

 

第一行中,轉(zhuǎn)換成了數(shù)組,,但是變成了 Object,,丟失了所有類(lèi)型信息。那其他兩個(gè)呢,?它們兩個(gè)使用起來(lái)非常地笨重,,第一個(gè)就顯得簡(jiǎn)潔得多。

 

后者根據(jù)需要的大小創(chuàng)建一個(gè)數(shù)組,,因此會(huì)有更好的性能(表現(xiàn)得更高效,,詳情參見(jiàn) truthy),但事實(shí)上,,真的會(huì)更高效嗎,?相反,它更慢,。

 

我們?yōu)槭裁慈绱岁P(guān)心這個(gè)問(wèn)題,?是否有更好的辦法處理它? 在 Java 11 中,,你可以這么做:

 

String[] strings_fun = list.toArray(String[]::new);

 

這是集合類(lèi)使用接收 IntFunction 的一個(gè)新的重載方法,。也就是說(shuō),這個(gè)方法根據(jù)輸入數(shù)據(jù)的長(zhǎng)度返回一個(gè)對(duì)應(yīng)長(zhǎng)度的數(shù)組,。在這里可以簡(jiǎn)潔的表示為 T[]::new,。

 

有意思的是,toArray(IntFunction) 的默認(rèn)實(shí)現(xiàn)總是將 0 傳遞給數(shù)組生成器,,最開(kāi)始,,我應(yīng)為這么做是為了更好的性能,現(xiàn)在我覺(jué)得,,有可能是因?yàn)樵谀承┘系膶?shí)現(xiàn)里面要去獲取它的大小,,代價(jià)是非常高的,所以沒(méi)有在 Collection 中做默認(rèn)實(shí)現(xiàn),。

 

雖然可以覆蓋像 ArrayList 這樣的具體集合,,但是在 Java 11 中,并沒(méi)有去做,,我猜是覺(jué)得不劃算,。

 

除非你已經(jīng)有一個(gè)數(shù)據(jù)了,否則請(qǐng)使用新的方法來(lái)替換 toArray(T[]) ,。當(dāng)然,,舊方法現(xiàn)在依然可以使用。

 

09

 

使用 'Optional::isEmpty' 而不是 'Present'

 

當(dāng)你經(jīng)常使用 Optional 的時(shí)候,,特別是在與大型的沒(méi)有做空檢查的代碼,,你需要經(jīng)常去檢查值是不是存在。 你會(huì)經(jīng)常使用 Optional::isPresent ,,但是你經(jīng)常會(huì)想知道哪一個(gè) Optional 是空的,。沒(méi)有問(wèn)題,使用 !opt.isPresent() 就可以了,,但是這樣對(duì)嗎,?

 

當(dāng)然,那樣寫(xiě)是沒(méi)有問(wèn)題的,,但是那樣寫(xiě)無(wú)法很好地理解其意思,。如果你在一個(gè)很長(zhǎng)的調(diào)用鏈中,想要知道它是不是空的,,你就得在最前面加一個(gè)“!”,。

 

publicbooleanneedsToCompleteAddress(User user){

 

return !getAddressRepository()

 

        .findAddressFor(user)

 

        .map(this::canonicalize)

 

        .filter(Address::isComplete)

 

        .isPresent();

 

}

 

這個(gè)“!”極易被遺忘掉。從 Java 11 開(kāi)始,,我們有了更好的解決方案:

 

publicbooleanneedsToCompleteAddress(User user){

 

return getAddressRepository()

 

        .findAddressFor(user)

 

        .map(this::canonicalize)

 

        .filter(Address::isComplete)

 

        .isEmpty();

 

}

 

10

 

使用 "Predicate::not" 來(lái)做取反

 

在說(shuō)關(guān)于 "not" 的之前,,我要說(shuō)一下 Predicate 接口的 negate 方法,他返回了一個(gè)新的 Predicate —— 執(zhí)行相同的測(cè)試代碼,,但是結(jié)果取反,。不幸的是,,我很少使用它:

 

// 打印非空字符

 

Stream.of("a""b""""c")

 

// 非常丑陋 ,使用 lamba 表達(dá)式,, 結(jié)果取反

 

    .filter(string -> !string.isBlank())

 

// 編譯錯(cuò)誤

 

    .filter((String::isBlank).negate())

 

// 強(qiáng)制轉(zhuǎn)型,,這個(gè)比lamba表達(dá)式還要丑陋

 

    .filter(((Predicate) String::isBlank).negate())

 

    .forEach(System.out::println);

 

問(wèn)題是我們很少能拿到 Predicate 的引用,更常見(jiàn)的情況是,,我想反轉(zhuǎn)一個(gè)方法,,但是編譯器需要知道目標(biāo),如果沒(méi)有目標(biāo),,編譯器不知道要把引用轉(zhuǎn)換成什么 ,。

 

所以當(dāng)你使用 (String::isBlank):negate() 的時(shí)候,String::isBlank 就沒(méi)有目標(biāo),,編譯器就會(huì)報(bào)錯(cuò),,雖然我們可以想辦法解決它,但是成本有多大呢,?

 

這里有一個(gè)簡(jiǎn)單的解決方案,,不需要你使用實(shí)例方法 negate ,而使用 Java 11 中新的靜態(tài)方法,。

 

Predicate.not(Predicate) 

 

Stream.of("a""b""""c")

 

// statically import `Predicate.not`

 

    .filter(not(String::isBlank))

 

    .forEach(System.out::println);

 

完美,!

 

11

 

使用 "Pattern:asMatchPredicate" 處理正則表達(dá)式

 

你有一個(gè)正則表達(dá)式,想要基于它做一些過(guò)濾,,你要怎么做,?

 

Pattern nonWordCharacter = Pattern.compile("\W");

 

Stream.of("Metallica""Mot?rhead")

 

    .filter(nonWordCharacter.asPredicate())

 

    .forEach(System.out::println);

 

我非常開(kāi)心,我能找到這種寫(xiě)法,,這是 Java 8 的寫(xiě)法,,很不幸,我錯(cuò)過(guò)了,。

 

在 Java 11 中,,有另外一個(gè)方法:Pattern::asMatchPredicate

 

它們有什么不同呢?

l  asPredicate 會(huì)檢查字符串或者其字串是否符合這個(gè)正則(他的行為像 s -> this.matcher(s).find() )

l  asMatchPredicate 只會(huì)檢查整個(gè)字符串是否符合這個(gè)正則(他的行為像 s -> this.matcher(s).matchs())

舉個(gè)例子:你現(xiàn)在有一個(gè)驗(yàn)證手機(jī)號(hào)的正則表達(dá)式,,但是這個(gè)正則表達(dá)式并不包含開(kāi)始符 ^ 和結(jié)束符 $,。下面代碼的執(zhí)行邏輯并不符合你的預(yù)期:

 

prospectivePhoneNumbers.stream()

 

    .filter(phoneNumberPatter.asPredicate())

 

    .forEach(this::robocall);

 

發(fā)現(xiàn)了它的錯(cuò)誤了嗎?"y u want numberz? +1-202-456-1414"會(huì)通過(guò)過(guò)濾檢測(cè),,因?yàn)樗艘粋€(gè)合法的手機(jī)號(hào),。但是使用 asMatchPredicate 就不能通過(guò),因?yàn)檎麄€(gè)字符串并不符合正則,。

 

12

 

結(jié)語(yǔ)

 

上面就是 11 個(gè)不為人知的瑰寶,,如果你看到這兒,那么恭喜你,,通過(guò)了本次學(xué)習(xí)??

 

1. 字符串

l  Stream lines()

l  String strip()

l  String stripLeading()

l  String stripTrailing()

l  boolean isBlank()

l  String repeat(int)

2. 路徑

l  static Path of(String, String...)

l  static Path of(URI)

3. 文件

l  String readString(Path) throws IOException

l  Path writeString(Path, CharSequence, OpenOption...) throwsIOException

l  Path writeString(Path, CharSequence, Charset, OpenOption...)throws IOException

4. I/O 

l  static InputStream nullInputStream()

l  static OutputStream nullOutputStream()

l  static Reader nullReader()

l  static Writer nullWriter()

5. 集合:T[] toArray(IntFunction)

 

6. 可選項(xiàng):boolean isEmpty()

 

7. 斷言:static Predicate not(Predicate)

 

8. 正則表達(dá)式:Predicate asMatchPredicate()

 

《The Coder》1 月刊

 

Java 和它的 2019

 

免費(fèi)

 

領(lǐng)取

 

原文 | https://blog./java/java-11-gems/

 

作者 | Nicolai Parlog,,《The Java Module System》作者,。

 

譯者 | 羅昭成

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多