科特林有ArrayDeque https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-array-deque/,它具有从列表中删除和添加元素的简单方法。
但它的容量并不有限。
使用自定义委托财产 https://kotlinlang.org/docs/delegated-properties.html是一种相当轻量级的方式来包装现有的ArrayDeque
这样我们就可以拦截呼叫并确保维持限制。
dequeLimiter
方法dequeLimiter
是基于NotNullVar https://github.com/JetBrains/kotlin/blob/34e57a45f2d4283be572137b4b497414b8833ee7/libraries/stdlib/src/kotlin/properties/Delegates.kt#L58代表。
每当内部deque
字段被读取或写入,它调用applyLimit()
这会删除任何多余的项目。
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
fun <E> dequeLimiter(limit: Int): ReadWriteProperty<Any?, ArrayDeque<E>> =
object : ReadWriteProperty<Any?, ArrayDeque<E>> {
private var deque: ArrayDeque<E> = ArrayDeque(limit)
private fun applyLimit() {
while (deque.size > limit) {
val removed = deque.removeFirst()
println("dequeLimiter removed $removed")
}
}
override fun getValue(thisRef: Any?, property: KProperty<*>): ArrayDeque<E> {
applyLimit()
return deque
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: ArrayDeque<E>) {
this.deque = value
applyLimit()
}
}
Usage
该委托适用于任何ArrayDeque
与by
关键字(参见the docs https://kotlinlang.org/docs/delegated-properties.html了解更多信息)。
此后,双端队列就可以正常使用,并且会自动受到限制。
fun main() {
// create a deque, and use our property delegate to intercept
// invocations and limit the size to 3
val limitedDeque: ArrayDeque<Int> by dequeLimiter(3)
// try adding 5 elements
(0..5).forEach {
limitedDeque.add(it)
println("limitedDeque: $limitedDeque")
}
/* output */
// limitedDeque: [0]
// limitedDeque: [0, 1]
// limitedDeque: [0, 1, 2]
// dequeLimiter removed 0
// limitedDeque: [1, 2, 3]
// dequeLimiter removed 1
// limitedDeque: [2, 3, 4]
// dequeLimiter removed 2
// limitedDeque: [3, 4, 5]
// try removing 5 elements
repeat(5) {
val removedLast = limitedDeque.removeLastOrNull()
println("removedLast: $removedLast")
println("limitedDeque: $limitedDeque")
}
/* output */
// removedLast: 5
// limitedDeque: [3, 4]
// removedLast: 4
// limitedDeque: [3]
// removedLast: 3
// limitedDeque: []
// removedLast: null
// limitedDeque: []
// removedLast: null
// limitedDeque: []
}