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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

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

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

大數據 java 代碼示例

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

我在本系列的每個部分中開發的示例是某種“提要處理程序”,用于處理文檔。 之前我們已經處理過特殊情況,但是我們將在功能上將它們作為數據來處理,更多。

如果您是第一次來,最好是從頭開始閱讀。 它有助于了解我們從何處開始以及如何在整個系列中繼續前進。

這些都是這些部分:

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

我將在每篇文章發表時更新鏈接。 如果您通過內容聯合組織來閱讀本文,請查看我博客上的原始文章。

每次代碼也被推送到這個GitHub項目 。

優雅失敗:回顧不多

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

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)}}

提要處理程序的主要職責是“處理”已更改文檔的列表,這似乎是每次在文檔中創建“資源”并進一步處理時。

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

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

當時的代碼如下:

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使我們能夠發出“異常”完成的信號,而無需使用諸如拋出Exception類的副作用。 在Java SDK中,這是封裝結果(成功或失敗)并與(例如) Optional (當前值或空值)共享monadic屬性的少數類之一。

在其他語言(例如Scala)中,有一種專用類型稱為Try 。

嘗試

從Scala嘗試文檔:

Try類型表示可能導致異常或返回成功計算值的計算。

使用Try Scala開發人員無需在可能發生異常的任何地方進行顯式異常處理。 如果我們也要在Java中使用它呢?

幸運的是,有一個名為Vavr的庫,其中包含我們可以在Java項目中使用的大量功能實用程序。

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

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

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

此類實際上是一個接口,并且有一堆默認方法,它們都返回實例本身,從而可以無限地鏈接廣告 ,例如:

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

返回最終值的方法:

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

將庫包含在項目中后,我們的代碼如何受益?

只需將我們的CompletableFuture替換為Try 。

因此,將我們的調用替換為thenApply/exceptionally到map/getOrElseGet '

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

變成

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

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

您可以像在Stream那樣窺視內部,例如

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

或者,您可以添加更多日志記錄以進行開發或故障排除,例如

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 ->// ... }

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

但是,您可以選擇“ Try CompletableFuture因為它似乎更自然地適合我們要實現的目標-計算沒有“未來主義”,也沒有計劃或“在某個時間點”可用。

但是還有更多。

從故障中恢復

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

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

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

它的Javadoc讀為:

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

換句話說:對于特定類型的異常,我們可以提供將失敗重新變為成功的功能。

首先,再次刪除多余的日志記錄和onSuccess/onFailure 。 現在,我們有一個Try ,一個成功場景的map和一個getOrElseGet ,錯誤場景的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)}}}// ...}

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

我們可以使用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())}

我們可以在自己的端查找一個重復項(因為它已經被處理過一次),所以我們的“ handleDuplicate”方法將返回任何令人滿意的流程 (即Resource ),并且繼續進行處理,就好像什么都沒有發生一樣。

當然,這只是一個示例,但是recover接受任何接受Throwable并返回Try函數。

多種故障:模式匹配

  • 如果我們實際上需要確保僅在出現DuplicateResourceException情況下才處理“重復”情況,而不是像現在這樣,僅處理任何異常,該怎么辦?
  • 如果API可能引發我們還需要專門處理的另一種類型的異常該怎么辦? 我們如何在處理多個異常類型的“選擇”之間進行選擇?

這就是使用Vavr的Match API進行模式匹配的地方。 我們可以創建一個Match的異常對象x (通過給使用recover ),同時給予靜態of -方法幾種情況選擇。

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

這個$實際上是Vavr的靜態方法,有幾種重載的版本返回一個模式 。

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

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; }

函數的組合( Case , $和Match )在Java中似乎有點奇怪,但是目前還沒有本機支持。 同時,您可以將Vavr用于此類功能。

在Java 12中,已經有兩個預覽功能正在努力使所有這些變為現實。 是JEP 305:instanceof的模式匹配和JEP 325:開關表達式

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

作為參考,代碼現在看起來如下:

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解析器無法正確理解lambda語法,因此上述示例在GitHub上的示例實際上無法正確解析為Groovy,但當然您也可以找到等效的Java版本 。

繼續,自己Try 。

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

如果您有任何意見或建議,我很想聽聽他們的意見!

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

大數據 java 代碼示例

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。