Skip to main content Skip to docs navigation

Data Structure Lists

ArrayList, FastArrayList, Array2, Deque, Pool, PriorityQueue, Queue, Stack, ListReader...

Document not reviewed yet, might be outdated. Please, let us know if you find something invalid here.
On this page

ArrayList: IntArrayList, FloatArrayList and DoubleArrayList

Kds provides specialized equivalents of ArrayList so it doesn’t involve object allocation through boxing. It uses typed arrays internally to store the elements of the ArrayList so it just requires one additional object allocation per list (the Array). It will just allocate a new object when the capacity of the list is exhausted.

*arrayListOf

You can construct literals using the *arrayListOf constructors:

val ilist = intArrayListOf(10, 20)
val flist = floatArrayListOf(10f, 20f)
val dlist = doubleArrayListOf(10.0, 20.0)

Expected behaviour

IntArrayList, FloatArrayList and DoubleArrayList work like a normal ArrayList but without incurring into boxing.

val list = IntArrayList()
list += 10
list += 20
list[0] = 15
println(list[0])
println(list.toList().map { it * 20 })
println(list.getCyclic(-1))

Optimized collection transformations

mapInt, mapFloat and mapDouble generate optimized *ArrayList. And *ArrayList have an specialized filter function too.

val filter = (0 until 10).mapInt { it * 3 }.filter { it % 2 == 0 }

Array2: Array2, IntArray2, FloatArray2, DoubleArray2

Array2 is a bidimensional version of Array variants. It includes a width and a height instead of size (length) measuing its dimensions.

It provides bidimensional indexers and some convenience methods.

val biarray = IntArray2(64, 64) { 0 }
val biarray = IntArray2(64, 64, 0)
biarray[0, 0] = 1
biarray.width == 64
biarray.height == 64

Internally it is represented as a single 1D Array and actual indices are computed using simple arithmetic.

Deque/CircularList: Deque, ByteDeque, IntDeque, FloatDeque, DoubleDeque

Deque variants (and its CircularList typealias) allows to insert and delete elements to/from the start or the end of the deque in constant time except when growing the collection. It can be used to implement queues or produce/consumers in an efficient way. The typed variants allow to reduce memory and allocation usage.

val l = IntDeque()
for (n in 0 until 1000) l.addFirst(n)
for (n in 0 until 1000) l.removeFirst()
for (n in 0 until 1000) l.addLast(n)

ListReader

A reader for lists. It can peek, read or expect a specific value in order.

val reader = listOf(1, 2, 3).reader()
assertEquals(true, reader.hasMore)
assertEquals(1, reader.peek())
assertEquals(1, reader.peek())
assertEquals(1, reader.read())
assertEquals(2, reader.read())
assertEquals(3, reader.expect(3))
assertEquals(false, reader.hasMore)

Pool

A simple pool implementation allowing to preallocate, to reset objects and to temporally allocate (freeing automatically) using an inline function. It accepts an instance allocator, and an optional function to reset instances.

val pool = Pool { Demo() }
pool.alloc { demo ->
    println("Temporarilly allocated $demo")
}
val pool = Pool(reset = {
    totalResetCount++
    it.x = 0
    it.y = 0
},  gen = {
    totalAllocCount++
    Demo()
})
val a = pool.alloc()
val b = pool.alloc()

assertEquals(0, pool.itemsInPool)
pool.free(c)
assertEquals(1, pool.itemsInPool)
pool.free(b)

pool.alloc {
    assertEquals(1, pool.itemsInPool)
}
assertEquals(2, pool.itemsInPool)

assertEquals(5, totalResetCount) // Number of resets
assertEquals(3, totalAllocCount) // Number of allocs

PriorityQueue: PriorityQueue, IntPriorityQueue, FloatPriorityQueue, DoublePriorityQueue

Provides a PriorityQueue that allows to insert items in a Queue by priority. It allows reordering specific items after modification.

val pq = IntPriorityQueue()
pq.add(10)
pq.add(15)
pq.add(5)
assertEquals(5, pq.removeHead())
assertEquals(10, pq.removeHead())
assertEquals(15, pq.removeHead())
assertEquals(0, pq.size)

Allows to provide a custom Comparator:

val pq = IntPriorityQueue { a, b -> (-a).compareTo(-b) }
pq.addAll(listOf(1, 2, 3, 4))
assertEquals(listOf(4, 3, 2, 1), pq.toList())

And to repriorize objects after modification:

val item = Item(10)
pq.add(item)
item.value = 20
pq.updateObject(item)

It is implemented using a Min Heap so addition, removing and updating happens in O(log(n)).

Queue: Queue, IntQueue, FloatQueue, DoubleQueue

A FIFO (First In First Out) collection.

val queue = IntQueue()
queue.enqueue(1)
queue.enqueue(2)
assertEquals(1, queue.dequeue())

Internally implemented using a Deque.

Stack: Stack, IntStack, FloatStack, DoubleStack

A LIFO (Last In First Out) collection.

val queue = IntStack()
queue.push(1)
queue.push(2)
assertEquals(2, queue.pop())

Internally implemented using an ArrayList.

Was this article useful?