Decommonize collection builders (#4157)

Decommonize collection builder implementations

(cherry picked from commit c960dc0af1f8940e519bf6c6c0886192d2ed88bb)
This commit is contained in:
Abduqodiri Qurbonzoda
2020-05-23 03:52:57 +03:00
committed by Vasily Levchenko
parent c6f11781fe
commit 7b49a052f9
9 changed files with 243 additions and 242 deletions
@@ -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()
}