Kotlin 中的驱逐队列

pra*_*lot 4 collections android kotlin

我需要一个集合:

  • 有固定的大小
  • 是可变的
  • 添加新元素后将重新索引元素,删除最旧的元素(如移位寄存器)

我认为 GuavaEvictingQueue和 Apache CommonsCircularFifoQueue就是我所需要的。

然而,我使用的是 Android,并希望 Kotlin 已经有类似的东西。但我还没找到;)

aSe*_*emy 5

Kotlin 有ArrayDeque,它具有从列表中删除和添加元素的简单方法。

但它的容量并不有限。

使用自定义委托属性是包装现有属性的一种相当轻量级的方法ArrayDeque,因此我们可以拦截调用并确保维持限制。

dequeLimiter

该方法dequeLimiter基于NotNullVar委托。

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()
    }
  }
Run Code Online (Sandbox Code Playgroud)

用法

委托适用于任何ArrayDeque具有by关键字的对象(有关更多信息,请参阅文档)。

此后,双端队列就可以正常使用,并且会自动受到限制。

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: []

}
Run Code Online (Sandbox Code Playgroud)