lambda 序列化_如何以及为什么要序列化Lambda
lambda 序列化
總覽
lambda序列化在許多用例中很有用,例如持久配置或作為遠(yuǎn)程資源的訪客模式 。
遠(yuǎn)程訪客
例如,因此我想訪問遠(yuǎn)程Map上的資源,可以使用get / put,但是說(shuō)我只想從Map的值中返回一個(gè)字段,我可以將lambda作為訪問者來(lái)提取信息。我想要。
MapView userMap =Chassis.acquireMap("users", String.class, UserInfo.class); userMap.put("userid", new UserInfo("User's Name"));// print out changesuserInfo.registerSubscriber(System.out::println);// obtain just the fullName without downloading the whole object String name= userMap.applyToKey("userid", u -> u.fullName);// increment a counter atomically and trigger // an updated event printed with the subscriber. userMap.asyncUpdateKey("userid", ui -> {ui.usageCounter++;return ui; });// increment a counter and return the userid int count = userMap.syncUpdateKey("userid",ui -> { ui.usageCounter++; return ui;},ui -> ui.usageCounter);如您所見,添加各種簡(jiǎn)單功能或調(diào)用方法來(lái)執(zhí)行所需的操作很容易。 唯一的問題是,默認(rèn)情況下,lambda無(wú)法序列化。
可序列化的Lambda
使Lambda可序列化的一種簡(jiǎn)單方法是將&的可轉(zhuǎn)換類型添加到引用lambda的實(shí)現(xiàn)的變量中。
Function<UserInfo, String> fullNameFunc = (Function<UserInfo,String> & Serializable) ui -> ui.fullName; String fullName = userInfo.applyToKey("userid", fullNameFunc);如您所見,這引入了很多樣板。 使用lambda的一個(gè)關(guān)鍵原因是避免樣板代碼,那么替代方法是什么?
使lambda可在您的API中序列化。
不幸的是,無(wú)法更改標(biāo)準(zhǔn)API或添加其子類,但是如果您擁有自己的API,則可以使用Serializable接口。
@FunctionalInterface public interface SerializableFunction<I, O> extends Function<I, O>, Serializable { }該接口可用作參數(shù)類型。
default <R> R applyToKey(K key, @NotNull SerializableFunction<E, R> function) {return function.apply(get(key)); }您的API用戶不必明確聲明lambda是可序列化的。
// obtain just the fullName without downloading the whole object String name= userMap.applyToKey("userid", u -> u.fullName);遠(yuǎn)程實(shí)現(xiàn)對(duì)lambda進(jìn)行序列化,然后在服務(wù)器上執(zhí)行該lambda并返回結(jié)果。
類似地,存在將lambda應(yīng)用于整個(gè)地圖的方法。
查詢和訂閱
為了支持查詢,如果要隱式添加Serializable,則不能使用內(nèi)置的stream()API。 但是,您可以創(chuàng)建一個(gè)盡可能相似的文件。
Map> collect = userMap.entrySet().query().filter(e -> e.getKey().matches("u*d")).map(e -> e.getValue()).collect(Collectors.groupingBy(u -> u.usageCounter));或作為過濾的訂閱。
// print userid which have a usageCounter > 10 each time it is incremented. userMap.entrySet().query().filter(e -> e.getValue().usageCounter > 10).map(e -> e.getKey()).subscribe(System.out::println);這與常規(guī)流API的不同之處在于,數(shù)據(jù)可以分布在許多服務(wù)器上,并且當(dāng)任何服務(wù)器上的數(shù)據(jù)發(fā)生更改時(shí),您都會(huì)得到回調(diào)。 在服務(wù)器上應(yīng)用過濾器和映射時(shí),只有您感興趣的數(shù)據(jù)才通過網(wǎng)絡(luò)發(fā)送。
Java序列化
Java序列化是一個(gè)很好的通用化,向后兼容的序列化庫(kù)。 替代方案嘗試解決的兩個(gè)最常見問題是性能和跨平臺(tái)序列化。
在上面的示例中,fullNameFunc序列化到700多個(gè)字節(jié),并且有非常有限的選項(xiàng)來(lái)優(yōu)化它以減小消息的大小或產(chǎn)生的垃圾量。 相比之下,簡(jiǎn)單的二進(jìn)制YAML序列化使用348,并提供更多選項(xiàng)來(lái)優(yōu)化序列化。
這就提出了如何使用替代,跨平臺(tái)或更快的序列化格式來(lái)序列化lambda的問題。
替代序列化
您可以加入當(dāng)前的序列化機(jī)制。 不支持此功能,它可以隨時(shí)更改,但是沒有其他受支持的方式來(lái)執(zhí)行此操作。
無(wú)論如何,您可以這樣做:
Method writeReplace = lambda.getClass().getDeclaredMethod("writeReplace"); writeReplace.setAccessible(true); SerializedLambda sl = (SerializedLambda) writeReplace.invoke(lambda);這為您提供了一個(gè)對(duì)象,您可以檢查該對(duì)象以提取lambda的內(nèi)容。 要么查看它調(diào)用什么方法,要么對(duì)其進(jìn)行序列化。 在反序列化方面,您可以重新創(chuàng)建該對(duì)象并可以在該對(duì)象上讀取Resolve。
標(biāo)準(zhǔn)API
當(dāng)前,沒有用于內(nèi)省lambda的標(biāo)準(zhǔn)API。 這樣做是有意進(jìn)行的,以便將來(lái)可以更改實(shí)現(xiàn),盡管沒有公共JEP可以這樣做。 但是,就像Unsafe是內(nèi)部API一樣,我期待有一天可以使用標(biāo)準(zhǔn)API,而不必深入研究JVM的內(nèi)部來(lái)實(shí)現(xiàn)解決方案。
結(jié)論
通過對(duì)API進(jìn)行一些更改,您可以使序列化lambda對(duì)開發(fā)人員而言基本上是透明的。 這使實(shí)現(xiàn)簡(jiǎn)單的分布式系統(tǒng)更容易使用,同時(shí)為您提供優(yōu)化方法。
翻譯自: https://www.javacodegeeks.com/2015/07/how-and-why-to-serialize-lambdas.html
lambda 序列化
總結(jié)
以上是生活随笔為你收集整理的lambda 序列化_如何以及为什么要序列化Lambda的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux中的正则表达式(linux 的
- 下一篇: 修复linux系统的方法(修复linux