ImmutableArrayList and listBuilder() prototype

TODO: lots of improvements, documentation, tests
This commit is contained in:
Stepan Koltsov
2012-05-17 16:37:03 +04:00
parent 942777205c
commit c40bb8c9b3
2 changed files with 150 additions and 0 deletions
@@ -0,0 +1,87 @@
package kotlin
import java.util.List
import java.util.AbstractList
private class ImmutableArrayList<T>(
private val array: Array<T>,
private val offset: Int,
private val length: Int
) : AbstractList<T>() {
{
// impossible
if (offset < 0) {
throw IllegalArgumentException("negative offset")
}
// impossible
if (length < 0) {
throw IllegalArgumentException("negative length")
}
// possible when builder is used from different threads
if (offset + length > array.size) {
throw IllegalArgumentException("offset + length > array.length")
}
}
protected fun indexInArray(index: Int): Int {
if (index < 0) {
throw IllegalArgumentException("negative index")
}
if (index >= length) {
throw IllegalArgumentException("index > length")
}
return index + offset
}
public override fun get(index: Int): T = array[indexInArray(index)] as T
public override fun size() : Int = length
public override fun subList(fromIndex: Int, toIndex: Int) : List<T> {
if (fromIndex < 0) {
throw IllegalArgumentException("negative from index")
}
if (toIndex < fromIndex) {
throw IllegalArgumentException("toIndex < fromIndex")
}
if (toIndex > length) {
throw IllegalArgumentException("fromIndex + toIndex > length")
}
return ImmutableArrayList(array, offset + fromIndex, toIndex - fromIndex)
}
// TODO: efficiently implement iterator and other stuff
}
// TODO: make val, see http://youtrack.jetbrains.com/issue/KT-2028
private fun emptyArray(): Array<Any?> = arrayOfNulls(0)
public class ImmutableArrayListBuilder<T>() {
private var array = emptyArray()
private var length = 0
public fun build(): List<T> {
val r = ImmutableArrayList<T>(array as Array<T>, 0, length)
array = emptyArray()
length = 0
return r
}
public fun ensureCapacity(capacity: Int) {
if (array.size < capacity) {
val newSize = Math.max(capacity, Math.max(array.size * 2, 11))
array = array.copyOf(newSize)
}
}
public fun add(item: T) {
ensureCapacity(length + 1)
array[length] = item
++length
}
}
// default list builder
fun <T> listBuilder() = ImmutableArrayListBuilder<T>()
@@ -0,0 +1,63 @@
package test.collection
import kotlin.test.*
import junit.framework.TestCase
import java.util.List
import java.util.Random
class ImmutableArrayListTest() : TestCase() {
fun testSimple() {
val builder = ImmutableArrayListBuilder<Int>()
builder.add(17)
val list = builder.build()
assertEquals(1, list.size())
assertEquals(17, list[0])
}
fun testGet() {
for (length in 0 .. 55) {
val list = buildIntArray(length, 19)
assertEquals(length, list.size)
checkList(list, length, 19)
}
}
private fun buildIntArray(length: Int, firstValue: Int): List<Int> {
val builder = ImmutableArrayListBuilder<Int>()
for (j in 0 .. length - 1) {
builder.add(firstValue + j)
}
return builder.build()
}
private fun checkList(list: List<Int>, expectedLength: Int, expectedFirstValue: Int) {
assertEquals(expectedLength, list.size)
for (i in 0 .. expectedLength - 1) {
assertEquals(expectedFirstValue + i, list[i])
}
try {
list[expectedLength]
fail()
} catch (e: IllegalArgumentException) {
// expected
}
}
fun testSublist() {
val r = Random(1)
for (i in 0 .. 200) {
val length = r.nextInt(55)
val list = buildIntArray(length, 23)
val fromIndex = r.nextInt(length + 1)
val toIndex = fromIndex + r.nextInt(length - fromIndex + 1)
val sublist = list.subList(fromIndex, toIndex)
checkList(sublist, toIndex - fromIndex, 23 + fromIndex)
}
}
}