如何在Kotlin中实现存储懒加载值的Map集合
解决方案
方案:自定义懒加载值的Map实现(零侵入原有类)
实现思路
不需要修改原有TableClass结构,也不需要写包装类转发方法,通过自定义标准Map接口的实现类,重写get方法,第一次访问对应key时才触发实例化,后续访问直接复用已生成的实例。
通用工具代码
fun <K, V> lazyMap(valueFactory: (key: K) -> V): Map<K, V> = object : Map<K, V> { // 内部存储已经实例化的键值对 private val cache = mutableMapOf<K, V>() override val size: Int get() = cache.size override fun isEmpty(): Boolean = cache.isEmpty() override fun containsKey(key: K): Boolean = cache.containsKey(key) override fun containsValue(value: V): Boolean = cache.containsValue(value) override val entries: Set<Map.Entry<K, V>> get() = cache.entries override val keys: Set<K> get() = cache.keys override val values: Collection<V> get() = cache.values // 核心逻辑:获取key时如果不存在则调用工厂方法实例化,并存入缓存 override fun get(key: K): V = cache.computeIfAbsent(key, valueFactory) }
如果需要线程安全的场景,只需要把内部的mutableMapOf替换为ConcurrentHashMap即可。
使用示例
// 直接声明符合标准Map接口的懒加载表,用法和普通Map完全一致 private val tableMap: Map<KeyClass, TableClass> = lazyMap { key -> // 这里写对应key的TableClass初始化逻辑,仅第一次访问该key时执行 val param = getTableInitParamByKey(key) TableClass(param) } // 后续使用和普通Map没有区别,第一次调用时才会实例化对应TableClass val result = tableMap[KeyClass.USER_TABLE]?.query()
补充说明
如果需要限制仅允许预定义的key访问,避免生成预期外的高成本实例,可以在初始化时增加合法key校验:
private val legalKeys = setOf(KeyClass.USER_TABLE, KeyClass.ORDER_TABLE, KeyClass.GOODS_TABLE) private val tableMap: Map<KeyClass, TableClass> = lazyMap { key -> require(key in legalKeys) { "不支持的表key: $key" } TableClass(getTableInitParamByKey(key)) }
内容的提问来源于stack exchange,提问作者Oliver Matthews
相关产品推荐
相关产品推荐

