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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

java

大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据

發(fā)布時(shí)間:2023/12/3 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大數(shù)據(jù) java 代碼示例

這是稱(chēng)為“ Functional Java by Example”的系列文章的第7部分。

我在本系列的每個(gè)部分中開(kāi)發(fā)的示例是某種“提要處理程序”,用于處理文檔。 之前我們已經(jīng)處理過(guò)特殊情況,但是我們將在功能上將它們作為數(shù)據(jù)來(lái)處理,更多。

如果您是第一次來(lái),最好是從頭開(kāi)始閱讀。 它有助于了解我們從何處開(kāi)始以及如何在整個(gè)系列中繼續(xù)前進(jìn)。

這些都是這些部分:

  • 第1部分–從命令式到聲明式
  • 第2部分–講故事
  • 第3部分–不要使用異常來(lái)控制流程
  • 第4部分–首選不變性
  • 第5部分–將I / O移到外部
  • 第6部分–用作參數(shù)
  • 第7部分–將失敗也視為數(shù)據(jù)
  • 第8部分–更多純函數(shù)

我將在每篇文章發(fā)表時(shí)更新鏈接。 如果您通過(guò)內(nèi)容聯(lián)合組織來(lái)閱讀本文,請(qǐng)查看我博客上的原始文章。

每次代碼也被推送到這個(gè)GitHub項(xiàng)目 。

優(yōu)雅失敗:回顧不多

這是我們以前留下的東西:

class FeedHandler {List handle(List changes,Function creator) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->creator.apply(doc).thenApply { resource ->setToProcessed(doc, resource)}.exceptionally { e ->setToFailed(doc, e)}.get()}}private static boolean isImportant(doc) {doc.type == 'important'}private static Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private static Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}

提要處理程序的主要職責(zé)是“處理”已更改文檔的列表,這似乎是每次在文檔中創(chuàng)建“資源”并進(jìn)一步處理時(shí)。

在上一部分中,該函數(shù)已抽象為一個(gè)函數(shù),該函數(shù)接受Doc并返回Resource ,在Java中如下所示: Function creator

您可以看到資源實(shí)際上包裝在CompletableFuture (CF)中,這使我們可以鏈接方法調(diào)用,例如thenApply和exceptionally 。 在第3部分(不要使用異常來(lái)控制流程) ,我們推出了exceptionally更換,我們使用了部分try-catch來(lái)應(yīng)對(duì)可能的例外創(chuàng)建資源時(shí)。

當(dāng)時(shí)的代碼如下:

try {def resource = createResource(doc)updateToProcessed(doc, resource) } catch (e) {updateToFailed(doc, e) }

我們將其替換為:

createResource(doc) .thenAccept { resource ->updateToProcessed(doc, resource) }.exceptionally { e ->updateToFailed(doc, e) }

CF使我們能夠發(fā)出“異常”完成的信號(hào),而無(wú)需使用諸如拋出Exception類(lèi)的副作用。 在Java SDK中,這是封裝結(jié)果(成功或失敗)并與(例如) Optional (當(dāng)前值或空值)共享monadic屬性的少數(shù)類(lèi)之一。

在其他語(yǔ)言(例如Scala)中,有一種專(zhuān)用類(lèi)型稱(chēng)為T(mén)ry 。

嘗試

從Scala嘗試文檔:

Try類(lèi)型表示可能導(dǎo)致異常或返回成功計(jì)算值的計(jì)算。

使用Try Scala開(kāi)發(fā)人員無(wú)需在可能發(fā)生異常的任何地方進(jìn)行顯式異常處理。 如果我們也要在Java中使用它呢?

幸運(yùn)的是,有一個(gè)名為Vavr的庫(kù),其中包含我們可以在Java項(xiàng)目中使用的大量功能實(shí)用程序。

Vavr Try文檔中的示例向我們展示了完全忘記異常是多么容易:

Try.of(() -> bunchOfWork()).getOrElse(other);

我們要么在成功時(shí)從bunchOfWork()獲得結(jié)果, bunchOfWork()在成功過(guò)程中因other而失敗。

此類(lèi)實(shí)際上是一個(gè)接口,并且有一堆默認(rèn)方法,它們都返回實(shí)例本身,從而可以無(wú)限地鏈接廣告 ,例如:

  • andFinally –提供最終嘗試行為,無(wú)論操作結(jié)果如何。
  • andThen –如果成功,則運(yùn)行給定的runnable,否則返回此Failure。
  • filter –如果是失敗或成功,并且值滿足謂詞,則返回此值。
  • onFailure –如果這是一次失敗,則消耗該throwable。
  • onSuccess –如果成功,則使用該值。
  • map –如果給定的函數(shù)成功,則運(yùn)行給定的檢查函數(shù),并將當(dāng)前表達(dá)式的結(jié)果傳遞給它。

返回最終值的方法:

  • get –如果成功則獲取此Try的結(jié)果,如果失敗則獲取throw。
  • getCause –如果失敗則獲取原因,如果成功則拋出。
  • getOrElse –返回基礎(chǔ)值(如果存在),否則返回另一個(gè)值。
  • getOrElseGet –返回基礎(chǔ)值(如果存在),否則返回另一個(gè)函數(shù)的值。
  • getOrElseThrow –返回基礎(chǔ)值(如果存在),否則拋出getOrElseThrow ()。
  • getOrElseTry –返回基礎(chǔ)值(如果存在),否則返回Try.of(supplier).get()的結(jié)果。
  • getOrNull –返回基礎(chǔ)值(如果存在),否則返回null 。

將庫(kù)包含在項(xiàng)目中后,我們的代碼如何受益?

只需將我們的CompletableFuture替換為T(mén)ry 。

因此,將我們的調(diào)用替換為thenApply/exceptionally到map/getOrElseGet '

creator.apply(doc) .thenApply { resource ->// ... }.exceptionally { e ->// ... }.get()

變成

creator.apply(doc) .map { resource ->// ... }.getOrElseGet { e ->// ... }

Try的map -method接受一個(gè)函數(shù),該函數(shù)在try為“成功”時(shí)運(yùn)行(如前所述)。 getOrElseGet方法可以在發(fā)生故障(例如異常)的情況下接受函數(shù)。

您可以像在Stream那樣窺視內(nèi)部,例如

creator.apply(doc) .peek { resource ->println "We've got a $resource" } .map { resource ->// ... }.getOrElseGet { e ->// ... }

或者,您可以添加更多日志記錄以進(jìn)行開(kāi)發(fā)或故障排除,例如

creator.apply(doc) .peek { resource ->println "We've got a $resource" }.onSuccess { resource ->println "Successfully created $resource" }.onFailure { e ->println "Bugger! Got a $e" }.map { resource ->// ... }.onSuccess { document ->println "Successfully processed $document" }.onFailure { e ->println "Bugger! Processing failed with $e" }.getOrElseGet { e ->// ... }

從表面上看,似乎沒(méi)有太大變化。 它只是將一組方法調(diào)用替換為其他方法調(diào)用,在這種情況下,也就足夠了。

但是,您可以選擇“ Try CompletableFuture因?yàn)樗坪醺匀坏剡m合我們要實(shí)現(xiàn)的目標(biāo)-計(jì)算沒(méi)有“未來(lái)主義”,也沒(méi)有計(jì)劃或“在某個(gè)時(shí)間點(diǎn)”可用。

但是還有更多。

從故障中恢復(fù)

現(xiàn)在我們得到的是,如果資源創(chuàng)建者API失敗,則將任何失敗很好地包裝在Try ,因此我們可以輕松地遵循成功或失敗的路徑。

但是,如果某些故障對(duì)我們有意義 ,并且在某些情況下我們希望以其他方式失敗的情況仍然成功,該怎么辦?

好吧,我們可以從失敗中恢復(fù)過(guò)來(lái) ,并按照自己的意愿修改代碼。 我們可以使用下面的Try方法,并使用漂亮的方法簽名,稱(chēng)為recover(Class exception, Function f) 。

它的Javadoc讀為:

如果是成功或失敗,并且原因不能從cause.getClass()分配,則返回此值。 否則,嘗試使用f恢復(fù)失敗的異常,即調(diào)用Try.of(()-> f.apply((X)getCause())。

換句話說(shuō):對(duì)于特定類(lèi)型的異常,我們可以提供將失敗重新變?yōu)槌晒Φ墓δ堋?

首先,再次刪除多余的日志記錄和onSuccess/onFailure 。 現(xiàn)在,我們有一個(gè)Try ,一個(gè)成功場(chǎng)景的map和一個(gè)getOrElseGet ,錯(cuò)誤場(chǎng)景的map :

class FeedHandler {List handle(List changes,Function creator) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->creator.apply(doc).map { resource ->setToProcessed(doc, resource)}.getOrElseGet { e ->setToFailed(doc, e)}}}// ...}

如果“資源創(chuàng)建” API(即creator#apply調(diào)用)拋出例如DuplicateResourceException信號(hào),該信號(hào)表明我們正在創(chuàng)建的資源是重復(fù)項(xiàng) ,那么它已經(jīng)存在 ,該怎么辦?

我們可以使用recover功能!

List handle(List changes,Function creator) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->creator.apply(doc).recover { t ->handleDuplicate(doc)}.map { resource ->setToProcessed(doc, resource)}.getOrElseGet { e ->setToFailed(doc, e)}}}private Resource handleDuplicate(Doc alreadyProcessed) {// find earlier saved, existing resource and return that onereturn repository.findById(alreadyProcessed.getApiId())}

我們可以在自己的端查找一個(gè)重復(fù)項(xiàng)(因?yàn)樗呀?jīng)被處理過(guò)一次),所以我們的“ handleDuplicate”方法將返回任何令人滿意的流程 (即Resource ),并且繼續(xù)進(jìn)行處理,就好像什么都沒(méi)有發(fā)生一樣。

當(dāng)然,這只是一個(gè)示例,但是recover接受任何接受Throwable并返回Try函數(shù)。

多種故障:模式匹配

  • 如果我們實(shí)際上需要確保僅在出現(xiàn)DuplicateResourceException情況下才處理“重復(fù)”情況,而不是像現(xiàn)在這樣,僅處理任何異常,該怎么辦?
  • 如果API可能引發(fā)我們還需要專(zhuān)門(mén)處理的另一種類(lèi)型的異常該怎么辦? 我們?nèi)绾卧谔幚矶鄠€(gè)異常類(lèi)型的“選擇”之間進(jìn)行選擇?

這就是使用Vavr的Match API進(jìn)行模式匹配的地方。 我們可以創(chuàng)建一個(gè)Match的異常對(duì)象x (通過(guò)給使用recover ),同時(shí)給予靜態(tài)of -方法幾種情況選擇。

recover { x -> Match(x).of(Case($(instanceOf(DuplicateResourceException.class)), t -> handleDuplicate(doc)),Case($(instanceOf(SpecialException.class)), t -> handleSpecial(t)) )}

這個(gè)$實(shí)際上是Vavr的靜態(tài)方法,有幾種重載的版本返回一個(gè)模式 。

這里的版本是接受Predicate的所謂“保護(hù)模式”。 請(qǐng)從Vavr Javadocs(使用純Java)中查看另一個(gè)示例:

String evenOrOdd(int num) {return Match(num).of(Case($(i -> i % 2 == 0), "even"),Case($(this::isOdd), "odd")); }boolean isOdd(int i) {return i % 2 == 1; }

函數(shù)的組合( Case , $和Match )在Java中似乎有點(diǎn)奇怪,但是目前還沒(méi)有本機(jī)支持。 同時(shí),您可以將Vavr用于此類(lèi)功能。

在Java 12中,已經(jīng)有兩個(gè)預(yù)覽功能正在努力使所有這些變?yōu)楝F(xiàn)實(shí)。 是JEP 305:instanceof的模式匹配和JEP 325:開(kāi)關(guān)表達(dá)式

在本期文章中,我們已經(jīng)看到我們可以將故障用作數(shù)據(jù),例如,走一條替代路徑并返回到功能流程。

作為參考,代碼現(xiàn)在看起來(lái)如下:

class FeedHandler {List<Doc> handle(List<Doc> changes,Function<Doc, Try<Resource>> creator) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->creator.apply(doc).recover { x -> Match(x).of(Case($(instanceOf(DuplicateResourceException.class)), t -> handleDuplicate(doc)),Case($(instanceOf(SpecialException.class)), t -> handleSpecial(t)))}.map { resource ->setToProcessed(doc, resource)}.getOrElseGet { e ->setToFailed(doc, e)}}}private Resource handleDuplicate(Doc alreadyProcessed) {// find earlier saved, existing resource and return that onereturn repository.findById(alreadyProcessed.getApiId())}private Resource handleSpecial(SpecialException e) {// handle special situationreturn new Resource()}private static boolean isImportant(doc) {doc.type == 'important'}private static Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private static Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}

由于Groovy 2.x解析器無(wú)法正確理解lambda語(yǔ)法,因此上述示例在GitHub上的示例實(shí)際上無(wú)法正確解析為Groovy,但當(dāng)然您也可以找到等效的Java版本 。

繼續(xù),自己Try 。

下次,我們將以更多功能結(jié)束本系列!

如果您有任何意見(jiàn)或建議,我很想聽(tīng)聽(tīng)他們的意見(jiàn)!

翻譯自: https://www.javacodegeeks.com/2019/05/functional-java-by-example-treat-failures-data-too.html

大數(shù)據(jù) java 代碼示例

總結(jié)

以上是生活随笔為你收集整理的大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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