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

歡迎訪問 生活随笔!

生活随笔

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

java

通过Java 8中的Applicative Builder组合多个异步结果

發(fā)布時間:2023/12/3 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通过Java 8中的Applicative Builder组合多个异步结果 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

幾個月前,我發(fā)布了一個出版物 ,在其中詳細解釋了我提出的名為Outcome的抽象,它通過強制使用語義幫助了我很多 沒有副作用的代碼。 通過遵循這種簡單(但功能強大)的約定,我最終將任何類型的故障(又稱Exception)都轉(zhuǎn)化為函數(shù)的顯式結(jié)果,從而使一切都更容易推論。 我不認識您,但是我厭倦了處理會破壞一切的異常,因此我做了一些事情,老實說,它確實工作得很好。 因此,在繼續(xù)講故事之前,我真的建議您仔細閱讀該文章。 現(xiàn)在,讓我們使用古怪的應(yīng)用思想解決一些異步問題,對吧?

這樣邪惡的事情來了

生活真是太好了,我們的編碼像以往一樣快速,干凈和可組合,但是,出乎意料的是,我們偶然發(fā)現(xiàn)了一個“缺失”功能(請大笑一下):我們需要將幾個異步 結(jié)果實例合并到一個阻礙時尚…。

受到這個想法的鼓舞,我開始工作。 我嘗試了很多時間,以尋求一種健壯而又簡單的方式來表達這種情況。 雖然新的ComposableFuture API原來比我期望的要好得多(盡管我仍然不明白為什么他們決定使用諸如applyAsync或thenComposeAsync之類的名稱,而不是map或flatMap ),但我總是以實現(xiàn)過于冗長和重復(fù)比較的方式結(jié)束我在Scala上所做的一些事情,但是經(jīng)過很長的“ Mate ”課程之后,我有了“嘿! 一刻”:為什么不使用類似于應(yīng)用程序的內(nèi)容 ?

問題

假設(shè)我們有兩個異步結(jié)果:

CompletableFuture<Outcome<String>> textf = completedFuture(maybe("And the number is %s!"));CompletableFuture<Outcome<Integer>> numberf = completedFuture(maybe(22));

還有一個愚蠢的實體Message:

public static class Message{private final String _text;private final Integer _number;private Message(String msg, Integer number){_text = msg;_number = number;}public String getContent(){return String.format(_text,_number);} }

我需要給定textf和numberf的東西,它會給我類似的東西

//After combining textf and numberf CompletableFuture<Outcome<Message>> message = ....

所以我給圣誕老人寫了一封信:

  • 我想僅當(dāng)兩個值都可用時才使用numberf返回的數(shù)字異步格式化textf返回的字符串,這意味著兩個期貨均成功完成,并且所有結(jié)果均未失敗。 當(dāng)然,我們需要不 阻塞。
  • 如果發(fā)生故障,我想收集在執(zhí)行textf和/或numberf期間發(fā)生的所有故障,然后再次將它們返回給調(diào)用方,而不會阻塞。
  • 我不想受到要組合的值數(shù)的限制,它必須能夠處理大量的異步結(jié)果。 我是說沒有阻止嗎? 你去...
  • 嘗試期間不死。
  • 適用于救援人員

    如果您考慮一下,那么一種簡單的方法來表達我們想要實現(xiàn)的目標(biāo)如下:

    // Given a String -> Given a number -> Format the message f: String -> Integer -> Message

    檢查f的定義,它表示類似:“給出一個String ,我將返回一個以Integer作為參數(shù)的函數(shù),該函數(shù)在應(yīng)用時將以這種方式返回Message類型的實例,而不是等待所有值一次可用,我們可以一次部分應(yīng)用一個值,以獲得對Message實例構(gòu)造過程的實際描述。 聽起來不錯。

    要實現(xiàn)這一點,如果我們可以使用構(gòu)造lambda Message:new并對其進行咖喱 ,再說一次,boom!,done !,將是非常了不起的,但是在Java中這是不可能的(以一種通用,美觀和簡潔的方式進行),因此對于為了我們的示例,我決定采用我們鐘愛的Builder模式,該模式確實可以勝任:

    public static class Builder implements WannabeApplicative<Message> {private String _text;private Integer _number;public Builder text(String text){_text=text;return this;}public Builder number(Integer number){_number=number;return this;}@Overridepublic Message apply() {return new Message(_text,_number);} }

    這是WannabeApplicative <T>的定義:

    public interface WannabeApplicative<V> {V apply(); }

    Disclamer : 對于那些功能 怪癖 ,這本身并不是適用的,我知道,但是我從中汲取了一些想法,并根據(jù)語言提供給我的工具對其進行了調(diào)整。 因此,如果您感到好奇,請查看此帖子以獲取更正式的示例。

    如果您仍在我身邊,我們可以同意,到目前為止,我們并沒有做過任何復(fù)雜的事情,但是現(xiàn)在我們需要表達一個構(gòu)建步驟,記住,該步驟必須是無阻塞的,并且能夠合并以前發(fā)生的任何故障可能發(fā)生在其他可能有新執(zhí)行的處決中。 因此,為了做到這一點,我提出了以下內(nèi)容:

    public static class CompositionSources<B> {private CompositionSources(){ }public interface Partial<B>{CompletableFuture<Outcome<B>> apply(CompletableFuture<Outcome<B>> b);}public interface MergingStage<B, V>{Partial<B> by(BiFunction<Outcome<B>, Outcome<V>, Outcome<B>> f);}public <V> MergingStage<B, V> value(CompletableFuture<Outcome<V>> value){return f -> builder-> builder.thenCombine(value, (b, v) -> f.apply(b, v).dependingOn(b).dependingOn(v));}public static <B> CompositionSources<B> stickedTo(Class<B> clazz){return new CompositionSources<>();} }

    首先,我們有兩個功能接口:一個是Partial <B> ,它表示將值懶惰地應(yīng)用于生成器 ,而第二個接口MergingStage <B,V>表示“如何”組合既是建設(shè)者又是價值 。 然后,我們得到了一個名為value的方法,給定類型為CompletableFuture <Outcome <V >>的實例,它將返回類型為MergingStage <B,V>的實例,并且信不信由你,這就是發(fā)生魔術(shù)的地方。 如果您還記得MergingState定義, 則將看到它是BiFunction ,其中第一個參數(shù)的類型為Outcome <B> ,第二個參數(shù)的類型為Outcome <V> 。 現(xiàn)在,如果遵循這些類型,則可以說出兩件事:一側(cè)的構(gòu)建過程的部分狀態(tài)(類型參數(shù)B)和需要應(yīng)用于構(gòu)建器當(dāng)前狀態(tài)的新值(類型參數(shù)V),以便在應(yīng)用時將生成一個新的構(gòu)建器實例,該實例具有“構(gòu)建順序中的下一個狀態(tài)”,由Partial <B>表示 。 最后但并非最不重要的一點,我們有stickedTo方法,它基本上是一個(糟糕的Java)技巧,可在定義構(gòu)建步驟時堅持使用特定的應(yīng)用程序類型(構(gòu)建器)。 例如,具有:

    CompositionSources<Builder> sources = CompositionSources.stickedTo(Builder.class);

    我可以為任何Builder實例定義部分值應(yīng)用程序,如下所示:

    //What we're gonna do with the async text when available Partial<Builder> textToApply = sources.value(textf).by((builder, text) -> builder.flatMapR(b -> text.mapR(b::text)));//Same thing for the number Partial<Builder> numberToApply = sources.value(numberf).by((builder, number) -> builder.flatMapR(b -> number.mapR(b::number)));

    看到我們還沒有建立任何東西,我們只是描述了當(dāng)時間到時我們想對每個值進行的操作 ,我們可能想在使用新值之前進行一些驗證(這是在結(jié)果發(fā)揮重要作用時),或者只是使用確實如此,這完全取決于我們,但主要要點是我們還沒有應(yīng)用任何東西。 為了這樣做,并最終收緊所有松散的末端,我想出了其他一些定義,如下所示:

    public static class FutureCompositions<V , A extends WannabeApplicative<V>>{private final Supplier<CompletableFuture<Outcome<A>>> _partial;private FutureCompositions(Supplier<CompletableFuture<Outcome<A>>> state){_partial=state;}public FutureCompositions<V, A> binding(Partial<A> stage){return new FutureCompositions<>(() -> stage.apply(_partial.get()));}public CompletableFuture<Outcome<V>> perform(){return _partial.get().thenApply(p -> p.mapR(WannabeApplicative::apply));}public static <V, A extends WannabeApplicative<V>> FutureCompositions<V, A> begin(A applicative){return new FutureCompositions<>(() -> completedFuture(maybe(applicative)));} }

    希望這不是那么令人頭疼,但我會盡力將其分解得盡可能清楚。 為了開始指定如何將整個事物組合在一起,您將從調(diào)用WannabeApplicative <V>類型的實例開始 ,在我們的示例中,它的類型參數(shù)V等于Builder 。

    FutureCompositions<Message, Builder> ab = begin(Message.applicative())

    看到,在調(diào)用begin之后 ,您將獲得一個FutureCompositions的新實例,其中包含一個延遲評估的部分狀態(tài) ,使其成為整個構(gòu)建過程狀態(tài)的唯一所有者,而這正是我們所做的一切的最終目標(biāo)到目前為止,我們已經(jīng)做好了充分的控制,以完全控制何時以及如何將事物組合在一起。 接下來,我們必須指定要合并的值,這就是綁定方法的用途:

    ab.binding(textToApply).binding(numberToApply);

    這樣,我們便可以使用先前定義的Partial實例為構(gòu)建器實例提供所有需要合并的值,以及每個實例應(yīng)該發(fā)生的情況的規(guī)范。 還可以看到,所有內(nèi)容仍在惰性評估中,什么都沒有發(fā)生,但是我們?nèi)匀欢询B了所有“步驟”,直到最終確定實現(xiàn)結(jié)果為止,這將在您調(diào)用perform時發(fā)生。

    CompletableFuture<Outcome<Message>> message = ab.perform();

    從那一刻起,一切都會展開,每個構(gòu)建階段都將得到評估,可以在結(jié)果實例中返回并收集故障,或者簡單地將新可用的值以一種或另一種方式提供給目標(biāo)構(gòu)建器實例,所有步驟將被執(zhí)行直到什么都不做。 我將嘗試描述如下情況

    如果您留意圖片的左側(cè),您可以輕松地看到我之前顯示的每個步驟是如何“定義的”,遵循先前的“聲明”箭頭方向,即您實際描述構(gòu)建過程的方式。 現(xiàn)在,從您調(diào)用perform的那一刻起,每個應(yīng)用實例(在我們的情況下請記住Builder )將被反方向延遲求值:它將首先求值堆棧中的最后一個指定階段,然后再求值下一個階段依次類推,直到達到建筑物定義的“起點”,它將開始展開或向上逐步展開評估,并使用MergingStage規(guī)范收集所有可能的信息 。

    而這僅僅是個開始…。

    我敢肯定,可以做很多事情來改善這個想法,例如:

    • 連續(xù)兩次調(diào)用CompositionSources.values()的 dependingOn 很爛 ,我覺得這太冗長了,我必須對此做些事情。
    • 我不太確定要繼續(xù)將結(jié)果實例傳遞給MergingStage ,如果在調(diào)用它之前解開要合并的值并只返回Either <Failure,V> ,它將看起來更干凈,更輕松-這將降低復(fù)雜性并提高靈活性關(guān)于幕后發(fā)生的事情。
    • 盡管使用Builder模式完成了這項工作,但是感覺還是很老套了 ,我很想輕松地構(gòu)造函數(shù),因此在我的待辦事項清單中是檢查jOOλ或Javaslang是否可以提供某些服務(wù)。
    • 更好的類型推斷,以便從代碼中消除任何不必要的干擾,例如, stickedTo方法,它的確是代碼的味道,我一開始就討厭。 絕對需要更多時間來找出從定義本身推斷應(yīng)用類型的另一種方法。

    非常歡迎您給我發(fā)送您可能有的任何建議和意見。 干杯,記住……

    翻譯自: https://www.javacodegeeks.com/2015/12/composing-multiple-async-results-via-applicative-builder-java-8.html

    總結(jié)

    以上是生活随笔為你收集整理的通过Java 8中的Applicative Builder组合多个异步结果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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