Kotlin 中的记忆功能
Memoization Function In Kotlin
我有一个现有的 class 实例方法 buildHierarchyUncached 其签名可以在下面找到。
private fun buildHierarchyUncached(date: LocalDate): Node { ... }
我想提供一个 public function buildHiearchy,它是 buildHierarchyUncached 的记忆版本。我可以接近我想要的:
val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)})
可以这样称呼:
hierarchyService.buildHiearchy(businessDate)
使用:
class Memoize<I, O>(val func: (I) -> O): (I) -> O{
val cache = hashMapOf<I, O>();
override fun invoke(p1: I): O {
return cache.getOrPut(p1, { func(p1) } )
}
}
我希望能够将记忆函数声明为函数而不是 属性,这不是什么大问题,但我认为这有助于提高可读性。像这样:
fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)})
但无法编译:"Type mismatch. Required Node. Found memoize."
另外,为什么这个编译不了?
val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)})
根据问题的性质,您需要一个 class 字段来存储您的缓存(缓存值或缓存对象或委托)。所以你必须在 class 的某个地方声明一个 val
,因为函数不能那样做。
请注意,当您声明您的 buildHiearchy
值时,您将两件事合二为一:将一个 Memoize<..>(..)
对象存储在 class 字段中,并获得 invoke()
功能(在其他地方声明,但仍然..)。我知道您无法在没有附加语法的情况下声明一个函数并获取字段存储。
代码段使用了过时的语法。像这样修复(没有括号):
val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)})
以下解决方案适用于单参数函数。如果您想创建函数 bar
的缓存版本,您只需像这样声明它:
val cachedBar = makeFunctionCache({ bar(it) })
该实现将缓存存储在一个闭包中,因此您无需将其放入专用的 class:
fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R {
val cache: MutableMap<X, R> = HashMap()
return {
cache.getOrPut(it, { fn(it) })
}
}
您可以使用 Map.computeIfAbsent
来实现您的目标,它看起来像这样:
val map = HashMap<String, Any>()
fun doSomething():Any{
return map.computeIfAbsent("functionKey") {
// do your calculation here
}
}
这样,计算只会执行一次并存储在地图中
我有一个现有的 class 实例方法 buildHierarchyUncached 其签名可以在下面找到。
private fun buildHierarchyUncached(date: LocalDate): Node { ... }
我想提供一个 public function buildHiearchy,它是 buildHierarchyUncached 的记忆版本。我可以接近我想要的:
val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)})
可以这样称呼:
hierarchyService.buildHiearchy(businessDate)
使用:
class Memoize<I, O>(val func: (I) -> O): (I) -> O{
val cache = hashMapOf<I, O>();
override fun invoke(p1: I): O {
return cache.getOrPut(p1, { func(p1) } )
}
}
我希望能够将记忆函数声明为函数而不是 属性,这不是什么大问题,但我认为这有助于提高可读性。像这样:
fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)})
但无法编译:"Type mismatch. Required Node. Found memoize."
另外,为什么这个编译不了?
val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)})
根据问题的性质,您需要一个 class 字段来存储您的缓存(缓存值或缓存对象或委托)。所以你必须在 class 的某个地方声明一个 val
,因为函数不能那样做。
请注意,当您声明您的 buildHiearchy
值时,您将两件事合二为一:将一个 Memoize<..>(..)
对象存储在 class 字段中,并获得 invoke()
功能(在其他地方声明,但仍然..)。我知道您无法在没有附加语法的情况下声明一个函数并获取字段存储。
代码段使用了过时的语法。像这样修复(没有括号):
val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)})
以下解决方案适用于单参数函数。如果您想创建函数 bar
的缓存版本,您只需像这样声明它:
val cachedBar = makeFunctionCache({ bar(it) })
该实现将缓存存储在一个闭包中,因此您无需将其放入专用的 class:
fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R {
val cache: MutableMap<X, R> = HashMap()
return {
cache.getOrPut(it, { fn(it) })
}
}
您可以使用 Map.computeIfAbsent
来实现您的目标,它看起来像这样:
val map = HashMap<String, Any>()
fun doSomething():Any{
return map.computeIfAbsent("functionKey") {
// do your calculation here
}
}
这样,计算只会执行一次并存储在地图中