Decommonize collection builders (#4157)
Decommonize collection builder implementations (cherry picked from commit c960dc0af1f8940e519bf6c6c0886192d2ed88bb)
This commit is contained in:
committed by
Vasily Levchenko
parent
c6f11781fe
commit
7b49a052f9
@@ -155,7 +155,7 @@ fun testEquals() {
|
||||
assertFalse(m == mapOf("a" to "1", "b" to "2", "c" to "5"))
|
||||
assertFalse(m == mapOf("a" to "1", "b" to "2"))
|
||||
assertEquals(m.keys, expected.keys)
|
||||
assertEquals(m.values, expected.values)
|
||||
assertEquals(m.values.toList(), expected.values.toList())
|
||||
assertEquals(m.entries, expected.entries)
|
||||
}
|
||||
|
||||
@@ -165,7 +165,6 @@ fun testHashCode() {
|
||||
assertEquals(expected.hashCode(), m.hashCode())
|
||||
assertEquals(expected.entries.hashCode(), m.entries.hashCode())
|
||||
assertEquals(expected.keys.hashCode(), m.keys.hashCode())
|
||||
assertEquals(listOf("1", "2", "3").hashCode(), m.values.hashCode())
|
||||
}
|
||||
|
||||
fun testToString() {
|
||||
@@ -184,9 +183,9 @@ fun testPutEntry() {
|
||||
assertTrue(m.entries.contains(e))
|
||||
assertTrue(m.entries.remove(e))
|
||||
assertTrue(mapOf("b" to "2", "c" to "3") == m)
|
||||
assertTrue(m.entries.add(e))
|
||||
assertEquals(null, m.put(e.key, e.value))
|
||||
assertTrue(expected == m)
|
||||
assertFalse(m.entries.add(e))
|
||||
assertEquals(e.value, m.put(e.key, e.value))
|
||||
assertTrue(expected == m)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,52 +9,46 @@ actual class ArrayList<E> private constructor(
|
||||
private var array: Array<E>,
|
||||
private var offset: Int,
|
||||
private var length: Int,
|
||||
private val backing: ArrayList<E>?
|
||||
) : MutableList<E>, RandomAccess, AbstractMutableCollection<E>() {
|
||||
private var isReadOnly: Boolean,
|
||||
private val backing: ArrayList<E>?,
|
||||
private val root: ArrayList<E>?
|
||||
) : MutableList<E>, RandomAccess, AbstractMutableList<E>() {
|
||||
|
||||
actual constructor() : this(10)
|
||||
|
||||
actual constructor(initialCapacity: Int) : this(
|
||||
arrayOfUninitializedElements(initialCapacity), 0, 0, null)
|
||||
arrayOfUninitializedElements(initialCapacity), 0, 0, false, null, null)
|
||||
|
||||
actual constructor(elements: Collection<E>) : this(elements.size) {
|
||||
addAll(elements)
|
||||
}
|
||||
|
||||
override actual val size : Int
|
||||
@PublishedApi
|
||||
internal fun build(): List<E> {
|
||||
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList
|
||||
checkIsMutable()
|
||||
isReadOnly = true
|
||||
return this
|
||||
}
|
||||
|
||||
override actual val size: Int
|
||||
get() = length
|
||||
|
||||
override actual fun isEmpty(): Boolean = length == 0
|
||||
|
||||
override actual fun get(index: Int): E {
|
||||
checkIndex(index)
|
||||
checkElementIndex(index)
|
||||
return array[offset + index]
|
||||
}
|
||||
|
||||
override actual operator fun set(index: Int, element: E): E {
|
||||
checkIndex(index)
|
||||
checkIsMutable()
|
||||
checkElementIndex(index)
|
||||
val old = array[offset + index]
|
||||
array[offset + index] = element
|
||||
return old
|
||||
}
|
||||
|
||||
override actual fun contains(element: E): Boolean {
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (array[offset + i] == element) return true
|
||||
i++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override actual fun containsAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!contains(it.next()))return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override actual fun indexOf(element: E): Int {
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
@@ -77,60 +71,68 @@ actual class ArrayList<E> private constructor(
|
||||
override actual fun listIterator(): MutableListIterator<E> = Itr(this, 0)
|
||||
|
||||
override actual fun listIterator(index: Int): MutableListIterator<E> {
|
||||
checkInsertIndex(index)
|
||||
checkPositionIndex(index)
|
||||
return Itr(this, index)
|
||||
}
|
||||
|
||||
override actual fun add(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
addAtInternal(offset + length, element)
|
||||
return true
|
||||
}
|
||||
|
||||
override actual fun add(index: Int, element: E) {
|
||||
checkInsertIndex(index)
|
||||
checkIsMutable()
|
||||
checkPositionIndex(index)
|
||||
addAtInternal(offset + index, element)
|
||||
}
|
||||
|
||||
override actual fun addAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
val n = elements.size
|
||||
addAllInternal(offset + length, elements, n)
|
||||
return n > 0
|
||||
}
|
||||
|
||||
override actual fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
checkInsertIndex(index)
|
||||
checkIsMutable()
|
||||
checkPositionIndex(index)
|
||||
val n = elements.size
|
||||
addAllInternal(offset + index, elements, n)
|
||||
return n > 0
|
||||
}
|
||||
|
||||
override actual fun clear() {
|
||||
checkIsMutable()
|
||||
removeRangeInternal(offset, length)
|
||||
}
|
||||
|
||||
override actual fun removeAt(index: Int): E {
|
||||
checkIndex(index)
|
||||
checkIsMutable()
|
||||
checkElementIndex(index)
|
||||
return removeAtInternal(offset + index)
|
||||
}
|
||||
|
||||
override actual fun remove(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
val i = indexOf(element)
|
||||
if (i >= 0) removeAt(i)
|
||||
return i >= 0
|
||||
}
|
||||
|
||||
override actual fun removeAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return retainOrRemoveAllInternal(offset, length, elements, false) > 0
|
||||
}
|
||||
|
||||
override actual fun retainAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return retainOrRemoveAllInternal(offset, length, elements, true) > 0
|
||||
}
|
||||
|
||||
override actual fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
|
||||
checkInsertIndex(fromIndex)
|
||||
checkInsertIndexFrom(toIndex, fromIndex)
|
||||
return ArrayList(array, offset + fromIndex, toIndex - fromIndex, this)
|
||||
checkRangeIndexes(fromIndex, toIndex)
|
||||
return ArrayList(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this, root ?: this)
|
||||
}
|
||||
|
||||
actual fun trimToSize() {
|
||||
@@ -139,12 +141,11 @@ actual class ArrayList<E> private constructor(
|
||||
array = array.copyOfUninitializedElements(length)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
final actual fun ensureCapacity(minCapacity: Int) {
|
||||
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList
|
||||
if (minCapacity > array.size) {
|
||||
var newSize = array.size * 3 / 2
|
||||
if (minCapacity > newSize)
|
||||
newSize = minCapacity
|
||||
val newSize = ArrayDeque.newCapacity(array.size, minCapacity)
|
||||
array = array.copyOfUninitializedElements(newSize)
|
||||
}
|
||||
}
|
||||
@@ -155,47 +156,46 @@ actual class ArrayList<E> private constructor(
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 1
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
val nextElement = array[offset + i]
|
||||
val nextHash = if (nextElement != null) nextElement.hashCode() else 0
|
||||
result = result * 31 + nextHash
|
||||
i++
|
||||
}
|
||||
return result
|
||||
return array.subarrayContentHashCode(offset, length)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return this.array.subarrayContentToString(offset, length)
|
||||
return array.subarrayContentToString(offset, length)
|
||||
}
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun checkElementIndex(index: Int) {
|
||||
if (index < 0 || index >= length) {
|
||||
throw IndexOutOfBoundsException("index: $index, size: $length")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPositionIndex(index: Int) {
|
||||
if (index < 0 || index > length) {
|
||||
throw IndexOutOfBoundsException("index: $index, size: $length")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRangeIndexes(fromIndex: Int, toIndex: Int) {
|
||||
if (fromIndex < 0 || toIndex > length) {
|
||||
throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex, size: $length")
|
||||
}
|
||||
if (fromIndex > toIndex) {
|
||||
throw IllegalArgumentException("fromIndex: $fromIndex > toIndex: $toIndex")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIsMutable() {
|
||||
if (isReadOnly || root != null && root.isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun ensureExtraCapacity(n: Int) {
|
||||
ensureCapacity(length + n)
|
||||
}
|
||||
|
||||
private fun checkIndex(index: Int) {
|
||||
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun checkInsertIndex(index: Int) {
|
||||
if (index < 0 || index > length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun checkInsertIndexFrom(index: Int, fromIndex: Int) {
|
||||
if (index < fromIndex || index > length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun contentEquals(other: List<*>): Boolean {
|
||||
if (length != other.size) return false
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (array[offset + i] != other[i]) return false
|
||||
i++
|
||||
}
|
||||
return true
|
||||
return array.subarrayContentEquals(offset, length, other)
|
||||
}
|
||||
|
||||
private fun insertAtInternal(i: Int, n: Int) {
|
||||
@@ -309,8 +309,8 @@ actual class ArrayList<E> private constructor(
|
||||
}
|
||||
|
||||
override fun set(element: E) {
|
||||
list.checkIndex(lastIndex)
|
||||
list.array[list.offset + lastIndex] = element
|
||||
check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." }
|
||||
list.set(lastIndex, element)
|
||||
}
|
||||
|
||||
override fun add(element: E) {
|
||||
@@ -326,3 +326,24 @@ actual class ArrayList<E> private constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Array<T>.subarrayContentHashCode(offset: Int, length: Int): Int {
|
||||
var result = 1
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
val nextElement = this[offset + i]
|
||||
result = result * 31 + nextElement.hashCode()
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun <T> Array<T>.subarrayContentEquals(offset: Int, length: Int, other: List<*>): Boolean {
|
||||
if (length != other.size) return false
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (this[offset + i] != other[i]) return false
|
||||
i++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import kotlin.native.internal.ExportForCppRuntime
|
||||
@PublishedApi
|
||||
internal fun <E> arrayOfUninitializedElements(size: Int): Array<E> {
|
||||
// TODO: special case for size == 0?
|
||||
require(size >= 0) { "capacity must be non-negative." }
|
||||
@Suppress("TYPE_PARAMETER_AS_REIFIED")
|
||||
return Array<E>(size)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,23 @@ public interface MutableIterable<out T> : Iterable<T> {
|
||||
}
|
||||
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return ArrayList<E>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return ArrayList<E>(capacity).apply(builderAction).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces each element in the list with a result of a transformation specified.
|
||||
*/
|
||||
|
||||
@@ -21,10 +21,12 @@ actual class HashMap<K, V> private constructor(
|
||||
override actual val size: Int
|
||||
get() = _size
|
||||
|
||||
private var keysView: HashSet<K>? = null
|
||||
private var keysView: HashMapKeys<K>? = null
|
||||
private var valuesView: HashMapValues<V>? = null
|
||||
private var entriesView: HashMapEntrySet<K, V>? = null
|
||||
|
||||
private var isReadOnly: Boolean = false
|
||||
|
||||
// ---------------------------- functions ----------------------------
|
||||
|
||||
actual constructor() : this(INITIAL_CAPACITY)
|
||||
@@ -44,15 +46,17 @@ actual class HashMap<K, V> private constructor(
|
||||
// This implementation doesn't use a loadFactor, this constructor is used for compatibility with common stdlib
|
||||
actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity)
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): Map<K, V> {
|
||||
checkIsMutable()
|
||||
isReadOnly = true
|
||||
return this
|
||||
}
|
||||
|
||||
override actual fun isEmpty(): Boolean = _size == 0
|
||||
override actual fun containsKey(key: K): Boolean = findKey(key) >= 0
|
||||
override actual fun containsValue(value: V): Boolean = findValue(value) >= 0
|
||||
|
||||
|
||||
operator fun set(key: K, value: V): Unit {
|
||||
put(key, value)
|
||||
}
|
||||
|
||||
override actual operator fun get(key: K): V? {
|
||||
val index = findKey(key)
|
||||
if (index < 0) return null
|
||||
@@ -60,6 +64,7 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
override actual fun put(key: K, value: V): V? {
|
||||
checkIsMutable()
|
||||
val index = addKey(key)
|
||||
val valuesArray = allocateValuesArray()
|
||||
if (index < 0) {
|
||||
@@ -73,11 +78,12 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
override actual fun putAll(from: Map<out K, V>) {
|
||||
checkIsMutable()
|
||||
putAllEntries(from.entries)
|
||||
}
|
||||
|
||||
override actual fun remove(key: K): V? {
|
||||
val index = removeKey(key)
|
||||
val index = removeKey(key) // mutability gets checked here
|
||||
if (index < 0) return null
|
||||
val valuesArray = valuesArray!!
|
||||
val oldValue = valuesArray[index]
|
||||
@@ -86,6 +92,7 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
override actual fun clear() {
|
||||
checkIsMutable()
|
||||
// O(length) implementation for hashArray cleanup
|
||||
for (i in 0..length - 1) {
|
||||
val hash = presenceArray[i]
|
||||
@@ -103,7 +110,7 @@ actual class HashMap<K, V> private constructor(
|
||||
override actual val keys: MutableSet<K> get() {
|
||||
val cur = keysView
|
||||
return if (cur == null) {
|
||||
val new = HashSet(this)
|
||||
val new = HashMapKeys(this)
|
||||
if (!isFrozen)
|
||||
keysView = new
|
||||
new
|
||||
@@ -133,7 +140,7 @@ actual class HashMap<K, V> private constructor(
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other === this ||
|
||||
(other is Map<*, *>) &&
|
||||
contentEquals(other)
|
||||
contentEquals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@@ -164,6 +171,10 @@ actual class HashMap<K, V> private constructor(
|
||||
private val capacity: Int get() = keysArray.size
|
||||
private val hashSize: Int get() = hashArray.size
|
||||
|
||||
internal fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun ensureExtraCapacity(n: Int) {
|
||||
ensureCapacity(length + n)
|
||||
}
|
||||
@@ -174,7 +185,7 @@ actual class HashMap<K, V> private constructor(
|
||||
if (capacity > newSize) newSize = capacity
|
||||
keysArray = keysArray.copyOfUninitializedElements(newSize)
|
||||
valuesArray = valuesArray?.copyOfUninitializedElements(newSize)
|
||||
presenceArray = presenceArray.copyOfUninitializedElements(newSize)
|
||||
presenceArray = presenceArray.copyOf(newSize)
|
||||
val newHashSize = computeHashSize(newSize)
|
||||
if (newHashSize > hashSize) rehash(newHashSize)
|
||||
} else if (length + capacity - _size > this.capacity) {
|
||||
@@ -265,6 +276,7 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
internal fun addKey(key: K): Int {
|
||||
checkIsMutable()
|
||||
retry@ while (true) {
|
||||
var hash = hash(key)
|
||||
// put is allowed to grow maxProbeDistance with some limits (resize hash on reaching limits)
|
||||
@@ -298,6 +310,7 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
internal fun removeKey(key: K): Int {
|
||||
checkIsMutable()
|
||||
val index = findKey(key)
|
||||
if (index < 0) return TOMBSTONE
|
||||
removeKeyAt(index)
|
||||
@@ -402,7 +415,7 @@ actual class HashMap<K, V> private constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun putEntry(entry: Map.Entry<K, V>): Boolean {
|
||||
private fun putEntry(entry: Map.Entry<K, V>): Boolean {
|
||||
val index = addKey(entry.key)
|
||||
val valuesArray = allocateValuesArray()
|
||||
if (index >= 0) {
|
||||
@@ -417,7 +430,7 @@ actual class HashMap<K, V> private constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean {
|
||||
private fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean {
|
||||
if (from.isEmpty()) return false
|
||||
ensureExtraCapacity(from.size)
|
||||
val it = from.iterator()
|
||||
@@ -430,6 +443,7 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
|
||||
internal fun removeEntry(entry: Map.Entry<K, V>): Boolean {
|
||||
checkIsMutable()
|
||||
val index = findKey(entry.key)
|
||||
if (index < 0) return false
|
||||
if (valuesArray!![index] != entry.value) return false
|
||||
@@ -437,87 +451,30 @@ actual class HashMap<K, V> private constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun removeAllEntries(elements: Collection<Map.Entry<K, V>>): Boolean {
|
||||
if (elements.isEmpty()) return false
|
||||
val it = entriesIterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
if (elements.contains(it.next())) {
|
||||
it.remove()
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
internal fun retainAllEntries(elements: Collection<Map.Entry<K, V>>): Boolean {
|
||||
val it = entriesIterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
if (!elements.contains(it.next())) {
|
||||
it.remove()
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
internal fun containsAllValues(elements: Collection<V>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!containsValue(it.next()))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun removeValue(element: V): Boolean {
|
||||
checkIsMutable()
|
||||
val index = findValue(element)
|
||||
if (index < 0) return false
|
||||
removeKeyAt(index)
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun removeAllValues(elements: Collection<V>): Boolean {
|
||||
val it = valuesIterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
if (elements.contains(it.next())) {
|
||||
it.remove()
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
internal fun retainAllValues(elements: Collection<V>): Boolean {
|
||||
val it = valuesIterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
if (!elements.contains(it.next())) {
|
||||
it.remove()
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
internal fun keysIterator() = KeysItr(this)
|
||||
internal fun valuesIterator() = ValuesItr(this)
|
||||
internal fun entriesIterator() = EntriesItr(this)
|
||||
|
||||
@kotlin.native.internal.CanBePrecreated
|
||||
private companion object {
|
||||
const val MAGIC = -1640531527 // 2654435769L.toInt(), golden ratio
|
||||
const val INITIAL_CAPACITY = 8
|
||||
const val INITIAL_MAX_PROBE_DISTANCE = 2
|
||||
const val TOMBSTONE = -1
|
||||
private const val MAGIC = -1640531527 // 2654435769L.toInt(), golden ratio
|
||||
private const val INITIAL_CAPACITY = 8
|
||||
private const val INITIAL_MAX_PROBE_DISTANCE = 2
|
||||
private const val TOMBSTONE = -1
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun computeHashSize(capacity: Int): Int = (capacity.coerceAtLeast(1) * 3).takeHighestOneBit()
|
||||
private fun computeHashSize(capacity: Int): Int = (capacity.coerceAtLeast(1) * 3).takeHighestOneBit()
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun computeShift(hashSize: Int): Int = hashSize.countLeadingZeroBits() + 1
|
||||
private fun computeShift(hashSize: Int): Int = hashSize.countLeadingZeroBits() + 1
|
||||
}
|
||||
|
||||
internal open class Itr<K, V>(
|
||||
@@ -538,6 +495,7 @@ actual class HashMap<K, V> private constructor(
|
||||
fun hasNext(): Boolean = index < map.length
|
||||
|
||||
fun remove() {
|
||||
map.checkIsMutable()
|
||||
map.removeKeyAt(lastIndex)
|
||||
lastIndex = -1
|
||||
}
|
||||
@@ -605,6 +563,7 @@ actual class HashMap<K, V> private constructor(
|
||||
get() = map.valuesArray!![index]
|
||||
|
||||
override fun setValue(newValue: V): V {
|
||||
map.checkIsMutable()
|
||||
val valuesArray = map.allocateValuesArray()
|
||||
val oldValue = valuesArray[index]
|
||||
valuesArray[index] = newValue
|
||||
@@ -622,82 +581,78 @@ actual class HashMap<K, V> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapKeys<E> internal constructor(
|
||||
private val backing: HashMap<E, *>
|
||||
) : MutableSet<E>, kotlin.native.internal.KonanSet<E>, AbstractMutableSet<E>() {
|
||||
|
||||
override val size: Int get() = backing.size
|
||||
override fun isEmpty(): Boolean = backing.isEmpty()
|
||||
override fun contains(element: E): Boolean = backing.containsKey(element)
|
||||
override fun getElement(element: E): E? = backing.getKey(element)
|
||||
override fun clear() = backing.clear()
|
||||
override fun add(element: E): Boolean = throw UnsupportedOperationException()
|
||||
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapValues<V> internal constructor(
|
||||
val backing: HashMap<*, V>
|
||||
) : MutableCollection<V> {
|
||||
) : MutableCollection<V>, AbstractMutableCollection<V>() {
|
||||
|
||||
override val size: Int get() = backing.size
|
||||
override fun isEmpty(): Boolean = backing.isEmpty()
|
||||
override fun contains(element: V): Boolean = backing.containsValue(element)
|
||||
override fun containsAll(elements: Collection<V>): Boolean = backing.containsAllValues(elements)
|
||||
override fun add(element: V): Boolean = throw UnsupportedOperationException()
|
||||
override fun addAll(elements: Collection<V>): Boolean = throw UnsupportedOperationException()
|
||||
override fun clear() = backing.clear()
|
||||
override fun iterator(): MutableIterator<V> = backing.valuesIterator()
|
||||
override fun remove(element: V): Boolean = backing.removeValue(element)
|
||||
override fun removeAll(elements: Collection<V>): Boolean = backing.removeAllValues(elements)
|
||||
override fun retainAll(elements: Collection<V>): Boolean = backing.retainAllValues(elements)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other === this ||
|
||||
other is Collection<*> &&
|
||||
contentEquals(other)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 1
|
||||
val it = iterator()
|
||||
while (it.hasNext()) {
|
||||
result = result * 31 + it.next().hashCode()
|
||||
}
|
||||
return result
|
||||
override fun removeAll(elements: Collection<V>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun toString(): String = collectionToString()
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun contentEquals(other: Collection<*>): Boolean {
|
||||
@Suppress("UNCHECKED_CAST") // todo: figure out something better
|
||||
return size == other.size && backing.containsAllValues(other as Collection<V>)
|
||||
override fun retainAll(elements: Collection<V>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapEntrySet<K, V> internal constructor(
|
||||
val backing: HashMap<K, V>
|
||||
) : MutableSet<MutableMap.MutableEntry<K, V>>, kotlin.native.internal.KonanSet<MutableMap.MutableEntry<K, V>> {
|
||||
) : MutableSet<MutableMap.MutableEntry<K, V>>, kotlin.native.internal.KonanSet<MutableMap.MutableEntry<K, V>>, AbstractMutableSet<MutableMap.MutableEntry<K, V>>() {
|
||||
|
||||
override val size: Int get() = backing.size
|
||||
override fun isEmpty(): Boolean = backing.isEmpty()
|
||||
override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = backing.containsEntry(element)
|
||||
override fun getElement(element: MutableMap.MutableEntry<K, V>): MutableMap.MutableEntry<K, V>? = backing.getEntry(element)
|
||||
override fun clear() = backing.clear()
|
||||
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = backing.putEntry(element)
|
||||
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = throw UnsupportedOperationException()
|
||||
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = throw UnsupportedOperationException()
|
||||
override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean = backing.removeEntry(element)
|
||||
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = backing.entriesIterator()
|
||||
override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.containsAllEntries(elements)
|
||||
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.putAllEntries(elements)
|
||||
override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.removeAllEntries(elements)
|
||||
override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.retainAllEntries(elements)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other === this || other is Set<*> && contentEquals(other)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 0
|
||||
val it = iterator()
|
||||
while (it.hasNext()) {
|
||||
result += it.next().hashCode()
|
||||
}
|
||||
return result
|
||||
override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun toString(): String = collectionToString()
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun contentEquals(other: Set<*>): Boolean {
|
||||
@Suppress("UNCHECKED_CAST") // todo: get rid of unchecked cast here somehow
|
||||
return size == other.size && backing.containsAllEntries(other as Collection<Map.Entry<*, *>>)
|
||||
override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
package kotlin.collections
|
||||
|
||||
actual class HashSet<E> internal constructor(
|
||||
val backing: HashMap<E, *>
|
||||
) : MutableSet<E>, AbstractMutableCollection<E>(), kotlin.native.internal.KonanSet<E> {
|
||||
private val backing: HashMap<E, *>
|
||||
) : MutableSet<E>, kotlin.native.internal.KonanSet<E>, AbstractMutableSet<E>() {
|
||||
|
||||
actual constructor() : this(HashMap<E, Nothing>())
|
||||
|
||||
@@ -20,6 +20,12 @@ actual class HashSet<E> internal constructor(
|
||||
// This implementation doesn't use a loadFactor
|
||||
actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity)
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): Set<E> {
|
||||
backing.build()
|
||||
return this
|
||||
}
|
||||
|
||||
override actual val size: Int get() = backing.size
|
||||
override actual fun isEmpty(): Boolean = backing.isEmpty()
|
||||
override actual fun contains(element: E): Boolean = backing.containsKey(element)
|
||||
@@ -29,46 +35,20 @@ actual class HashSet<E> internal constructor(
|
||||
override actual fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
||||
override actual fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||
|
||||
override actual fun containsAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!contains(it.next()))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override actual fun addAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
if (add(it.next()))
|
||||
updated = true
|
||||
}
|
||||
return updated
|
||||
backing.checkIsMutable()
|
||||
return super.addAll(elements)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other === this ||
|
||||
(other is Set<*>) &&
|
||||
contentEquals(
|
||||
@Suppress("UNCHECKED_CAST") (other as Set<E>))
|
||||
override actual fun removeAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 0
|
||||
val it = iterator()
|
||||
while (it.hasNext()) {
|
||||
result += it.next().hashCode()
|
||||
}
|
||||
return result
|
||||
override actual fun retainAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
|
||||
override fun toString(): String = collectionToString()
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun contentEquals(other: Set<E>): Boolean = size == other.size && containsAll(other)
|
||||
}
|
||||
|
||||
// This hash set keeps insertion order.
|
||||
|
||||
@@ -5,6 +5,23 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
return HashMap<K, V>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
return HashMap<K, V>(capacity).apply(builderAction).build()
|
||||
}
|
||||
|
||||
|
||||
// creates a singleton copy of map, if there is specialization available in target platform, otherwise returns itself
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline actual fun <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = toSingletonMap()
|
||||
@@ -19,14 +36,3 @@ internal actual fun <K, V> Map<out K, V>.toSingletonMap(): Map<K, V>
|
||||
*/
|
||||
@PublishedApi
|
||||
internal actual fun mapCapacity(expectedSize: Int) = expectedSize
|
||||
|
||||
/**
|
||||
* Checks a collection builder function capacity argument.
|
||||
* Does nothing, capacity is validated in List/Set/Map constructor
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@PublishedApi
|
||||
internal actual fun checkBuilderCapacity(capacity: Int) {
|
||||
require(capacity >= 0) { "capacity must be non-negative." }
|
||||
}
|
||||
@@ -50,9 +50,3 @@ public interface MutableSet<E> : Set<E>, MutableCollection<E> {
|
||||
override fun retainAll(elements: Collection<E>): Boolean
|
||||
override fun clear(): Unit
|
||||
}
|
||||
|
||||
// TODO: Add SingletonSet class
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
// TODO: Add SingletonSet class
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return HashSet<E>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return HashSet<E>(capacity).apply(builderAction).build()
|
||||
}
|
||||
Reference in New Issue
Block a user