Created
February 7, 2018 21:37
-
-
Save thibseisel/5dcf569aff9ce43cda5497b426e72bb0 to your computer and use it in GitHub Desktop.
An IntArrayList implementation based on the original ArrayList written in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.thibseisel.kblock.utils | |
import java.util.* | |
/** | |
* Default initial capacity. | |
*/ | |
private const val DEFAULT_CAPACITY = 10 | |
/** | |
* The maximum size of array to allocate. | |
* Some VMs reserve some header words in an array. | |
* Attempt to allocate larger arrays may result in `OutOfMemoryError`s. | |
*/ | |
private const val MAX_ARRAY_SIZE = Int.MAX_VALUE - 8 | |
/** | |
* Shared empty array instance used for empty instances. | |
*/ | |
private val EMPTY_ELEMENT_DATA = IntArray(0) | |
/** | |
* Shared empty array instance used for default sized empty instances. | |
* We distinguish this from [EMPTY_ELEMENT_DATA] to know how much to inflate | |
* when first element is added. | |
*/ | |
private val DEFAULTCAPACITY_EMPTY_ELEMENTDATA = IntArray(0) | |
class IntArrayList : AbstractMutableList<Int>, RandomAccess, Cloneable { | |
/** | |
* The array into which elements of the list are stored. | |
* The capacity of thie ArrayList is the length of this array buffer. | |
*/ | |
private var elementData: IntArray | |
/** | |
* Constructs an empty list with the specified initial capacity. | |
* | |
* @param initialCapacity The initial capacity of the list. Must not be negative. | |
* @throws IllegalArgumentException if the specified initial capacity is negative. | |
*/ | |
constructor(initialCapacity: Int) { | |
elementData = when { | |
initialCapacity > 0 -> IntArray(initialCapacity) | |
initialCapacity == 0 -> EMPTY_ELEMENT_DATA | |
else -> throw IllegalArgumentException("Illegal Capacity: $initialCapacity") | |
} | |
} | |
/** | |
* Constructs an empty list with an initial capacity of ten. | |
*/ | |
constructor() { | |
elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA | |
} | |
/** | |
* Constructs a list containing the elements of the specified array in the same order. | |
* | |
* @param source The array whose elements are to be placed into this list. | |
*/ | |
constructor(source: IntArray) { | |
elementData = if (source.isNotEmpty()) source.copyOf() else EMPTY_ELEMENT_DATA | |
} | |
/** | |
* Trim the capacity of this list instance to be the list's current size. | |
* An application can use this operation to minimize memory usage. | |
*/ | |
fun trimToSize() { | |
modCount++ | |
if (size < elementData.size) { | |
elementData = if (size == 0) EMPTY_ELEMENT_DATA else elementData.copyOf(size) | |
} | |
} | |
/** | |
* Increases the capacity of this list if necessary to ensure that it can hold at least | |
* the number of elements specified by the minimum capacity parameter. | |
* | |
* @param minCapacity The desired minimum capacity. | |
*/ | |
fun ensureCapacity(minCapacity: Int) { | |
val minExpand = if (elementData === DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 0 else DEFAULT_CAPACITY | |
if (minCapacity > minExpand) { | |
ensureExplicitCapacity(minCapacity) | |
} | |
} | |
private fun ensureCapacityInternal(minCapacity: Int) { | |
val targetMinCapacity = if (elementData === DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { | |
maxOf(DEFAULT_CAPACITY, minCapacity) | |
} else minCapacity | |
ensureExplicitCapacity(targetMinCapacity) | |
} | |
private fun ensureExplicitCapacity(minCapacity: Int) { | |
modCount++ | |
// Overflow conscious code | |
if (minCapacity - elementData.size > 0) { | |
grow(minCapacity) | |
} | |
} | |
/** | |
* Increases the capacity to ensure that it can hold at least | |
* the number of elements specified by the minimum capacity parameter. | |
* | |
* @param minCapacity The desired minimum capacity. | |
*/ | |
private fun grow(minCapacity: Int) { | |
val oldCapacity = elementData.size | |
val newCapacity = (oldCapacity + (oldCapacity shr 1)).coerceIn(minCapacity, MAX_ARRAY_SIZE) | |
elementData = elementData.copyOf(newCapacity) | |
} | |
/** | |
* The number of elements in this list. | |
*/ | |
override var size: Int = 0 | |
private set | |
/** | |
* Returns `true` if this list contains no elements. | |
*/ | |
override fun isEmpty() = size == 0 | |
override fun indexOf(element: Int): Int { | |
for (i in 0 until size) { | |
if (element == elementData[i]) return i | |
} | |
return -1 | |
} | |
override fun lastIndexOf(element: Int): Int { | |
for (i in (size - 1) downTo 0) { | |
if (element == elementData[i]) return i | |
} | |
return -1 | |
} | |
/** | |
* Returns a deep copy of this list. | |
* Elements themselves *are* copied. | |
*/ | |
public override fun clone(): Any { | |
try { | |
val clone = super.clone() as IntArrayList | |
clone.elementData = elementData.copyOf(size) | |
clone.modCount = 0 | |
return clone | |
} catch (e: CloneNotSupportedException) { | |
// This shouldn't happen, since we are Cloneable | |
throw InternalError(e) | |
} | |
} | |
fun toIntArray() = elementData.copyOf(size) | |
override fun toArray(): Array<Any> = Array(size, elementData::get) | |
override fun get(index: Int): Int { | |
rangeCheck(index) | |
return elementData[index] | |
} | |
override fun set(index: Int, element: Int): Int { | |
rangeCheck(index) | |
val oldValue = elementData[index] | |
elementData[index] = element | |
return oldValue | |
} | |
override fun add(element: Int): Boolean { | |
ensureCapacityInternal(size + 1) // Increments modCount!! | |
elementData[size++] = element | |
return true | |
} | |
override fun add(index: Int, element: Int) { | |
rangeCheckForAdd(index) | |
ensureCapacityInternal(size + 1) // Increments modCount!! | |
System.arraycopy(elementData, index, elementData, index + 1, size - index) | |
elementData[index] = element | |
size++ | |
} | |
override fun remove(element: Int): Boolean { | |
for (index in 0 until size) { | |
if (element == elementData[index]) { | |
fastRemove(index) | |
return true | |
} | |
} | |
return false | |
} | |
private fun fastRemove(index: Int) { | |
modCount++ | |
val numMoved = size - index -1 | |
if (numMoved > 0) { | |
System.arraycopy(elementData, index + 1, elementData, index, numMoved) | |
} | |
// No need to clear the removed value ; just decrement size | |
size-- | |
} | |
override fun clear() { | |
modCount++ | |
// No need to rewrite all elements. | |
size = 0 | |
} | |
private fun rangeCheck(index: Int) { | |
if (index >= size) { | |
throw IndexOutOfBoundsException(outOfBoundsMsg(index)) | |
} | |
} | |
private fun rangeCheckForAdd(index: Int) { | |
} | |
private fun outOfBoundsMsg(index: Int) = "index: $index, Size: $size" | |
override fun removeAt(index: Int): Int { | |
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. | |
} | |
inner class ListIterator : IntIterator() { | |
private var index = 0 | |
override fun hasNext() = index < size | |
override fun nextInt(): Int { | |
if (!hasNext()) throw NoSuchElementException() | |
return elementData[index++] | |
} | |
} | |
} | |
private fun hugeCapacity(minCapacity: Int): Int { | |
if (minCapacity < 0) throw OutOfMemoryError() | |
return if (minCapacity > MAX_ARRAY_SIZE) Int.MAX_VALUE else MAX_ARRAY_SIZE | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment