Functional Map API:处理单个条目

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

在这篇博文中,我们将继续介绍作为 Infinispan 8.0.0.Final 的一部分发布的实验性 Functional Map API,重点介绍如何使用单键操作来操作数据。

正如 Functional Map API 介绍 中提到的,可以对功能图执行三种类型的操作:只读操作(通过 ReadOnlyMap 执行)、只写操作(通过 WriteOnlyMap 执行)和读写操作(通过 ReadWriteMap ) 和 .

首先,我们需要构造 ReadOnlyMap WriteOnlyMap ReadWriteMap 的实例以便能够使用它们:


 import org.infinispan.AdvancedCache;
import org.infinispan.commons.api.functional.FunctionalMap.*;
import org.infinispan.functional.impl.*;
import org.infinispan.manager.DefaultCacheManager;

DefaultCacheManager cacheManager = new DefaultCacheManager(); AdvancedCache<String, String> cache = cacheManager.<String, String>getCache().getAdvancedCache(); FunctionalMapImpl<String, String> functionalMap = FunctionalMapImpl.create(cache);

ReadOnlyMap<String, String> readOnlyMap = ReadOnlyMapImpl.create(functionalMap); WriteOnlyMap<String, String> writeOnlyMap = WriteOnlyMapImpl.create(functionalMap); ReadWriteMap<String, String> readWriteMap = ReadWriteMapImpl.create(functionalMap);

接下来,让我们看看所有三种类型的操作,将它们链接起来以存储单个键/值对以及一些元数据,然后读取它并最终删除并返回先前存储的数据:


 import org.infinispan.AdvancedCache;
import org.infinispan.commons.api.functional.FunctionalMap.*;
import org.infinispan.functional.impl.*;
import org.infinispan.manager.DefaultCacheManager;

DefaultCacheManager cacheManager = new DefaultCacheManager(); AdvancedCache<String, String> cache = cacheManager.<String, String>getCache().getAdvancedCache(); FunctionalMapImpl<String, String> functionalMap = FunctionalMapImpl.create(cache);

ReadOnlyMap<String, String> readOnlyMap = ReadOnlyMapImpl.create(functionalMap); WriteOnlyMap<String, String> writeOnlyMap = WriteOnlyMapImpl.create(functionalMap); ReadWriteMap<String, String> readWriteMap = ReadWriteMapImpl.create(functionalMap);

此示例演示了使用 Functional Map API 处理单个条目的一些关键方面:

  • 单一入口方法是异步返回 CompletableFuture 实例,它提供组合和链式操作的方法,因此可以感觉到它们是按顺序执行的。不幸的是,Java 没有 Haskell 的 do 表示法 Scala 的 for comprehensions 以使其更容易接受,但好消息是 Java 终于提供了以非阻塞方式使用 CompletableFutures 的机制,即使它们比提议的更冗长在其他语言中。
  • WriteOnlyMap 的所有数据处理方法都返回 CompletableFuture<Void> ,这意味着用户可以知道操作何时完成,但除此之外别无其他,因为函数可以提供无法提前计算或在函数外部计算的任何内容。
  • ReadOnlyMap (和 ReadWriteMap )中大多数数据处理方法的返回类型都非常灵活。因此,函数可以决定返回值信息或元数据,或者为了方便起见,它还可以返回它接收到的作为参数的 ReadEntryView。这对于想要返回值和元数据参数信息的用户很有用。
  • 上面演示的读写操作展示了如何删除条目并返回先前关联的值。在这种特殊情况下,我们知道有一个与条目关联的值,因此我们直接调用了 ReadEntryView.get() ,但如果我们不确定该值是否存在,则应调用 ReadEntryView.find() 并返回 可选 实例代替。
  • 在该示例中, Lifespan 元数据参数 是使用 Java 8 中可用的新 Java Time API 构造的,但只要转换为输入条目期间的毫秒数,也可以使用 java.util.concurrent.TimeUnit 完成同样的操作应该可以访问。
  • 基于生命周期的到期与其他 Infinispan API 一样工作,因此您可以轻松修改示例以降低生命周期,等待持续时间过去,然后验证该值是否不再存在。

如果存储常量值,可以使用 WriteOnlyMap.eval(K, Consumer) 代替 WriteOnlyMap.eval(K, V, Consumer) ,使代码更清晰,但如果值是可变的, 则 WriteOnlyMap.eval(K, V, Consumer) 应该尽可能避免函数捕获外部变量。很显然,functional map 暴露的操作并不能覆盖所有场景,可能会出现函数捕获外部变量的情况,但一般来说,应该是少数。这是一个示例,显示如何在需要外部变量捕获的情况下实现 ConcurrentMap.replace(K, V, V)


 import org.infinispan.AdvancedCache;
import org.infinispan.commons.api.functional.FunctionalMap.*;
import org.infinispan.functional.impl.*;
import org.infinispan.manager.DefaultCacheManager;

DefaultCacheManager cacheManager = new DefaultCacheManager(); AdvancedCache<String, String> cache = cacheManager.<String, String>getCache().getAdvancedCache(); FunctionalMapImpl<String, String> functionalMap = FunctionalMapImpl.create(cache);

ReadOnlyMap<String, String> readOnlyMap = ReadOnlyMapImpl.create(functionalMap); WriteOnlyMap<String, String> writeOnlyMap = WriteOnlyMapImpl.create(functionalMap); ReadWriteMap<String, String> readWriteMap = ReadWriteMapImpl.create(functionalMap);

我们没有向 API 添加 WriteOnly.eval(K, V, V, Consumer) 的原因是基于值相等的替换比较只是一种可以执行的替换操作。在其他情况下,基于元数据参数的比较可能更合适,例如 Hot Rod 替换操作,其中版本(一种元数据参数)相等性是确定是否应该进行替换的决定性因素。

在下一篇博文中,我们将研究如何使用 Functional Map API 处理多个条目。