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

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

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

纹理和基元_通过粘性仙人掌基元进行延迟加载和缓存

發(fā)布時(shí)間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 纹理和基元_通过粘性仙人掌基元进行延迟加载和缓存 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

紋理和基元

您顯然知道什么是延遲加載 ,對(duì)嗎? 而且您無(wú)疑知道緩存 。 據(jù)我所知,Java中沒(méi)有一種優(yōu)雅的方法來(lái)實(shí)現(xiàn)它們中的任何一個(gè)。 這是我在Cactoos原語(yǔ)的幫助下為自己找到的。

Matteo Garrone的《 Reality》(2012年)

假設(shè)我們需要一個(gè)可以加密某些文本的對(duì)象。 以一種更加面向?qū)ο蟮姆绞街v,它將封裝文本并成為其加密形式。 這是我們將如何使用它( 首先創(chuàng)建測(cè)試 ):

interface Encrypted {String asString() throws IOException; } Encrypted enc = new EncryptedX("Hello, world!"); System.out.println(enc.asString());

現(xiàn)在,讓我們以一種非常原始的方式用一個(gè)主要的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)它。 加密機(jī)制只會(huì)在傳入數(shù)據(jù)中的每個(gè)字節(jié)上加上+1 ,并且會(huì)假設(shè)加密不會(huì)破壞任何內(nèi)容(一個(gè)非常愚蠢的假設(shè),但對(duì)于本示例而言,它將起作用):

class Encrypted1 implements Encrypted {private final String text;Encrypted1(String txt) {this.data = txt;}@Overridepublic String asString() {final byte in = this.text.getBytes();final byte[] out = new byte[in.length];for (int i = 0; i < in.length; ++i) {out[i] = (byte) (in[i] + 1);}return new String(out);} }

到目前為止看起來(lái)正確嗎? 我測(cè)試了它 ,而且效果很好。 如果輸入是"Hello, world!" ,輸出將為"Ifmmp-!xpsme\"" 。

接下來(lái),假設(shè)我們希望我們的類接受InputStream和String 。 我們想這樣稱呼它,例如:

Encrypted enc = new Encrypted2(new FileInputStream("/tmp/hello.txt") ); System.out.println(enc.toString());

這是最明顯的實(shí)現(xiàn),具有兩個(gè)主要的構(gòu)造函數(shù)(同樣,實(shí)現(xiàn)是原始的,但是可以工作):

class Encrypted2 implements Encrypted {private final String text;Encrypted2(InputStream input) throws IOException {ByteArrayOutputStream baos =new ByteArrayOutputStream();while (true) {int one = input.read();if (one < 0) {break;}baos.write(one);}this.data = new String(baos.toByteArray());}Encrypted2(String txt) {this.text = txt;}// asString() is exactly the same as in Encrypted1 }

從技術(shù)上講,它是可行的,但是流讀取是在構(gòu)造函數(shù)內(nèi)部進(jìn)行的,這是不正確的做法 。 主要構(gòu)造函數(shù)只能執(zhí)行屬性分配,而次要構(gòu)造函數(shù)只能創(chuàng)建新對(duì)象。

讓我們嘗試重構(gòu)并引入延遲加載:

class Encrypted3 {private String text;private final InputStream input;Encrypted3(InputStream stream) {this.text = null;this.input = stream;}Encrypted3(String txt) {this.text = txt;this.input = null;}@Overridepublic String asString() throws IOException {if (this.text == null) {ByteArrayOutputStream baos =new ByteArrayOutputStream();while (true) {int one = input.read();if (one < 0) {break;}baos.write(one);}this.text = new String(baos.toByteArray());}final byte in = this.text.getBytes();final byte[] out = new byte[in.length];for (int i = 0; i < in.length; ++i) {out[i] = (byte) (in[i] + 1);}return new String(out);} }

效果很好,但看起來(lái)很丑。 最丑陋的部分當(dāng)然是這兩行:

this.text = null; this.input = null;

它們使對(duì)象可變,并且使用NULL 。 丑陋,相信我。 不幸的是,延遲加載和NULL引用總是在經(jīng)典示例中并存 。 但是,有一種更好的方法來(lái)實(shí)現(xiàn)它。 讓我們重構(gòu)類,這次使用Cactoos的 Scalar :

class Encrypted4 implements Encrypted {private final IoCheckedScalar<String> text;Encrypted4(InputStream stream) {this(() -> {ByteArrayOutputStream baos =new ByteArrayOutputStream();while (true) {int one = stream.read();if (one < 0) {break;}baos.write(one);}return new String(baos.toByteArray());});}Encrypted4(String txt) {this(() -> txt);}Encrypted4(Scalar<String> source) {this.text = new IoCheckedScalar<>(source);}@Overridepublic String asString() throws IOException {final byte[] in = this.text.value().getBytes();final byte[] out = new byte[in.length];for (int i = 0; i < in.length; ++i) {out[i] = (byte) (in[i] + 1);}return new String(out);}

現(xiàn)在看起來(lái)好多了。 首先,只有一個(gè)主要構(gòu)造函數(shù)和兩個(gè)次要構(gòu)造函數(shù)。 其次,對(duì)象是不可變的 。 第三,還有很多改進(jìn)的余地:我們可以添加更多的構(gòu)造函數(shù)來(lái)接受其他數(shù)據(jù)源,例如File或byte數(shù)組。

簡(jiǎn)而言之,應(yīng)該以“惰性”方式加載的屬性在對(duì)象內(nèi)部表示為“功能”(Java 8中的lambda表達(dá)式 )。 在我們觸摸該屬性之前,不會(huì)加載該屬性。 一旦我們需要使用它,函數(shù)就會(huì)被執(zhí)行并得到結(jié)果。

這段代碼有一個(gè)問(wèn)題。 每當(dāng)我們調(diào)用asString() ,它將讀取輸入流,這顯然是行不通的,因?yàn)橹挥械谝淮瘟鞑艜?huì)有數(shù)據(jù)。 在每個(gè)后續(xù)調(diào)用中,流都將為空。 因此,我們需要確保this.text.value()僅執(zhí)行一次封裝的Scalar 。 所有以后的調(diào)用都必須返回以前計(jì)算的值。 因此,我們需要對(duì)其進(jìn)行緩存 。 方法如下:

class Encrypted5 implements Encrypted {private final IoCheckedScalar<String> text;// same as above in Encrypted4Encrypted5(Scalar<String> source) {this.data = new IoCheckedScalar<>(new StickyScalar<>(source));}// same as above in Encrypted4

此StickyScalar將確保僅對(duì)其方法value()的第一次調(diào)用將傳遞給封裝的Scalar 。 所有其他呼叫將接收第一個(gè)呼叫的結(jié)果。

要解決的最后一個(gè)問(wèn)題是關(guān)于并發(fā)性。 我們上面的代碼不是線程安全的。 如果我創(chuàng)建Encrypted5的實(shí)例并將其傳遞給同時(shí)調(diào)用asString()兩個(gè)線程,則結(jié)果將是不可預(yù)測(cè)的,這僅僅是因?yàn)镾tickyScalar不是線程安全的。 不過(guò),還有另一個(gè)可以幫助我們的原語(yǔ),稱為SyncScalar :

class Encrypted5 implements Encrypted {private final IoCheckedScalar<String> text;// same as above in Encrypted4Encrypted5(Scalar<String> source) {this.data = new IoCheckedScalar<>(new SyncScalar<>(new StickyScalar<>(source)));}// same as above in Encrypted4

現(xiàn)在我們很安全,設(shè)計(jì)優(yōu)雅。 它包括延遲加載和緩存。

我現(xiàn)在在許多項(xiàng)目中都使用這種方法,而且看起來(lái)很方便,清晰且面向?qū)ο蟆?

您可能還會(huì)發(fā)現(xiàn)這些相關(guān)的帖子很有趣: 為什么InputStream設(shè)計(jì)錯(cuò)誤 ; 嘗試。 最后。 如果。 不。 空值。 ; 每個(gè)私有靜態(tài)方法都是新類的候選人 ; 我將如何重新設(shè)計(jì)equals() ; 對(duì)象行為不可配置 ;

翻譯自: https://www.javacodegeeks.com/2017/10/lazy-loading-caching-via-sticky-cactoos-primitives.html

紋理和基元

總結(jié)

以上是生活随笔為你收集整理的纹理和基元_通过粘性仙人掌基元进行延迟加载和缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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