I need a collection that:
I think Guava's EvictingQueue and Apache Commons CircularFifoQueue is what I need.
However, I am on Android, and was hoping Kotlin already has something similar. But I did not find yet ;)
Kotlin has ArrayDeque, which has simple methods for removing and adding elements to a list.
It doesn't have a limited capacity though.
Using a custom Delegated property is a fairly lightweight way to wrap an existing ArrayDeque so we can intercept calls and ensure the limit is maintained.
dequeLimiterThe method dequeLimiter is based on the NotNullVar delegate.
Whenever the internal deque field is read or written, it calls applyLimit() and this removes any excess items.
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()
}
}
The delegate is applied on any ArrayDeque with the by keyword (see the docs for more info).
After this, the deque can be used as normal and will be automatically limited.
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: []
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With