diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ArraySet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ArraySet.kt
index 6d7a336..0c7ac8e 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ArraySet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ArraySet.kt
@@ -59,132 +59,37 @@
  * @constructor Creates a new empty ArraySet. The default capacity of an array map is 0, and
  * will grow once items are added to it.
  */
-public class ArraySet<E> @JvmOverloads constructor(capacity: Int = 0) :
-    MutableCollection<E>, MutableSet<E> {
+public expect class ArraySet<E> @JvmOverloads constructor(
+    capacity: Int = 0
+) : MutableCollection<E>, MutableSet<E> {
 
-    private var hashes: IntArray = EMPTY_INTS
-    private var array: Array<Any?> = EMPTY_OBJECTS
+    internal var hashes: IntArray
+    internal var array: Array<Any?>
 
-    private var _size = 0
-
+    internal var _size: Int
     override val size: Int
-        get() = _size
 
     /**
      * Create a new ArraySet with the mappings from the given ArraySet.
      */
-    public constructor(set: ArraySet<out E>?) : this(capacity = 0) {
-        if (set != null) {
-            addAll(set)
-        }
-    }
+    public constructor(set: ArraySet<out E>?)
 
     /**
      * Create a new ArraySet with the mappings from the given [Collection].
      */
-    public constructor(set: Collection<E>?) : this(capacity = 0) {
-        if (set != null) {
-            addAll(set)
-        }
-    }
+    public constructor(set: Collection<E>?)
 
     /**
      * Create a new ArraySet with items from the given array.
      */
-    public constructor(array: Array<out E>?) : this(capacity = 0) {
-        if (array != null) {
-            for (value in array) {
-                add(value)
-            }
-        }
-    }
-
-    init {
-        if (capacity > 0) {
-            allocArrays(capacity)
-        }
-    }
-
-    private fun binarySearchInternal(hash: Int): Int =
-        try {
-            binarySearch(hashes, _size, hash)
-        } catch (e: IndexOutOfBoundsException) {
-            throw ConcurrentModificationException()
-        }
-
-    private fun indexOf(key: Any?, hash: Int): Int {
-        val n = _size
-
-        // Important fast case: if nothing is in here, nothing to look for.
-        if (n == 0) {
-            return -1
-        }
-        val index = binarySearchInternal(hash)
-
-        // If the hash code wasn't found, then we have no entry for this key.
-        if (index < 0) {
-            return index
-        }
-
-        // If the key at the returned index matches, that's what we want.
-        if (key == array[index]) {
-            return index
-        }
-
-        // Search for a matching key after the index.
-        var end = index + 1
-        while (end < n && hashes[end] == hash) {
-            if (key == array[end]) {
-                return end
-            }
-            end++
-        }
-
-        // Search for a matching key before the index.
-        var i = index - 1
-        while (i >= 0 && hashes[i] == hash) {
-            if (key == array[i]) {
-                return i
-            }
-            i--
-        }
-
-        // Key not found -- return negative value indicating where a
-        // new entry for this key should go.  We use the end of the
-        // hash chain to reduce the number of array entries that will
-        // need to be copied when inserting.
-        return end.inv()
-    }
-
-    private fun indexOfNull(): Int = indexOf(key = null, hash = 0)
-
-    private fun allocArrays(size: Int) {
-        hashes = IntArray(size)
-        array = arrayOfNulls(size)
-    }
-
-    private inline fun printlnIfDebug(message: () -> String) {
-        if (DEBUG) {
-            println(message())
-        }
-    }
+    public constructor(array: Array<out E>?)
 
     /**
      * Make the array map empty.  All storage is released.
      *
      * @throws ConcurrentModificationException if concurrent modifications detected.
      */
-    override fun clear() {
-        if (_size != 0) {
-            hashes = EMPTY_INTS
-            array = EMPTY_OBJECTS
-            _size = 0
-        }
-        @Suppress("KotlinConstantConditions")
-        if (_size != 0) {
-            throw ConcurrentModificationException()
-        }
-    }
+    override fun clear()
 
     /**
      * Ensure the array map can hold at least [minimumCapacity]
@@ -192,21 +97,7 @@
      *
      * @throws ConcurrentModificationException if concurrent modifications detected.
      */
-    public fun ensureCapacity(minimumCapacity: Int) {
-        val oSize: Int = _size
-        if (hashes.size < minimumCapacity) {
-            val ohashes = hashes
-            val oarray = array
-            allocArrays(minimumCapacity)
-            if (_size > 0) {
-                ohashes.copyInto(destination = hashes, endIndex = _size)
-                oarray.copyInto(destination = array, endIndex = _size)
-            }
-        }
-        if (_size != oSize) {
-            throw ConcurrentModificationException()
-        }
-    }
+    public fun ensureCapacity(minimumCapacity: Int)
 
     /**
      * Check whether a value exists in the set.
@@ -214,8 +105,7 @@
      * @param element The value to search for.
      * @return Returns true if the value exists, else false.
      */
-    override operator fun contains(element: E): Boolean =
-        indexOf(element) >= 0
+    override operator fun contains(element: E): Boolean
 
     /**
      * Returns the index of a value in the set.
@@ -223,23 +113,20 @@
      * @param key The value to search for.
      * @return Returns the index of the value if it exists, else a negative integer.
      */
-    public fun indexOf(key: Any?): Int =
-        if (key == null) indexOfNull() else indexOf(key = key, hash = key.hashCode())
+    public fun indexOf(key: Any?): Int
 
     /**
      * Return the value at the given index in the array.
+     *
      * @param index The desired index, must be between 0 and [size]-1.
      * @return Returns the value stored at the given index.
      */
-    @Suppress("UNCHECKED_CAST")
-    public fun valueAt(index: Int): E =
-        array[index] as E
+    public fun valueAt(index: Int): E
 
     /**
-     * Return true if the array map contains no items.
+     * Return `true` if the array map contains no items.
      */
-    override fun isEmpty(): Boolean =
-        _size <= 0
+    override fun isEmpty(): Boolean
 
     /**
      * Adds the specified object to this set. The set is not modified if it
@@ -249,98 +136,15 @@
      * @return `true` if this set is modified, `false` otherwise.
      * @throws ConcurrentModificationException if concurrent modifications detected.
      */
-    override fun add(element: E): Boolean {
-        val oSize = _size
-        val hash: Int
-        var index: Int
-        if (element == null) {
-            hash = 0
-            index = indexOfNull()
-        } else {
-            hash = element.hashCode()
-            index = indexOf(element, hash)
-        }
-
-        if (index >= 0) {
-            return false
-        }
-
-        index = index.inv()
-        if (oSize >= hashes.size) {
-            val n =
-                when {
-                    oSize >= BASE_SIZE * 2 -> oSize + (oSize shr 1)
-                    oSize >= BASE_SIZE -> BASE_SIZE * 2
-                    else -> BASE_SIZE
-                }
-
-            printlnIfDebug { "$TAG add: grow from ${hashes.size} to $n" }
-
-            val ohashes = hashes
-            val oarray = array
-            allocArrays(n)
-
-            if (oSize != _size) {
-                throw ConcurrentModificationException()
-            }
-
-            if (hashes.isNotEmpty()) {
-                printlnIfDebug { "$TAG add: copy 0-$oSize to 0" }
-                ohashes.copyInto(destination = hashes, endIndex = ohashes.size)
-                oarray.copyInto(destination = array, endIndex = oarray.size)
-            }
-        }
-
-        if (index < oSize) {
-            printlnIfDebug { "$TAG add: move $index-${oSize - index} to ${index + 1}" }
-
-            hashes.copyInto(
-                destination = hashes,
-                destinationOffset = index + 1,
-                startIndex = index,
-                endIndex = oSize
-            )
-            array.copyInto(
-                destination = array,
-                destinationOffset = index + 1,
-                startIndex = index,
-                endIndex = oSize
-            )
-        }
-
-        if (oSize != _size || index >= hashes.size) {
-            throw ConcurrentModificationException()
-        }
-
-        hashes[index] = hash
-        array[index] = element
-        _size++
-        return true
-    }
+    override fun add(element: E): Boolean
 
     /**
      * Perform a [add] of all values in [array]
+     *
      * @param array The array whose contents are to be retrieved.
      * @throws ConcurrentModificationException if concurrent modifications detected.
      */
-    public fun addAll(array: ArraySet<out E>) {
-        val n = array._size
-        ensureCapacity(_size + n)
-        if (_size == 0) {
-            if (n > 0) {
-                array.hashes.copyInto(destination = hashes, endIndex = n)
-                array.array.copyInto(destination = this.array, endIndex = n)
-                if (0 != _size) {
-                    throw ConcurrentModificationException()
-                }
-                _size = n
-            }
-        } else {
-            for (i in 0 until n) {
-                add(array.valueAt(i))
-            }
-        }
-    }
+    public fun addAll(array: ArraySet<out E>)
 
     /**
      * Removes the specified object from this set.
@@ -348,125 +152,23 @@
      * @param element the object to remove.
      * @return `true` if this set was modified, `false` otherwise.
      */
-    override fun remove(element: E): Boolean {
-        val index = indexOf(element)
-        if (index >= 0) {
-            removeAt(index)
-            return true
-        }
-        return false
-    }
+    override fun remove(element: E): Boolean
 
     /**
      * Remove the key/value mapping at the given index.
+     *
      * @param index The desired index, must be between 0 and [size]-1.
      * @return Returns the value that was stored at this index.
      * @throws ConcurrentModificationException if concurrent modifications detected.
      */
-    public fun removeAt(index: Int): E {
-        val oSize = _size
-        val old = array[index]
-        if (oSize <= 1) {
-            // Now empty.
-            printlnIfDebug { "$TAG remove: shrink from ${hashes.size} to 0" }
-            clear()
-        } else {
-            val nSize = oSize - 1
-            if (hashes.size > (BASE_SIZE * 2) && (_size < hashes.size / 3)) {
-                // Shrunk enough to reduce size of arrays.  We don't allow it to
-                // shrink smaller than (BASE_SIZE*2) to avoid flapping between
-                // that and BASE_SIZE.
-                val n = if (_size > BASE_SIZE * 2) _size + (_size shr 1) else BASE_SIZE * 2
-                printlnIfDebug { "$TAG remove: shrink from ${hashes.size} to $n" }
-                val ohashes = hashes
-                val oarray = array
-                allocArrays(n)
-                if (index > 0) {
-                    printlnIfDebug { "$TAG remove: copy from 0-$index to 0" }
-                    ohashes.copyInto(destination = hashes, endIndex = index)
-                    oarray.copyInto(destination = array, endIndex = index)
-                }
-                if (index < nSize) {
-                    printlnIfDebug { "$TAG remove: copy from ${index + 1}-$nSize to $index" }
-                    ohashes.copyInto(
-                        destination = hashes,
-                        destinationOffset = index,
-                        startIndex = index + 1,
-                        endIndex = nSize + 1
-                    )
-                    oarray.copyInto(
-                        destination = array,
-                        destinationOffset = index,
-                        startIndex = index + 1,
-                        endIndex = nSize + 1
-                    )
-                }
-            } else {
-                if (index < nSize) {
-                    printlnIfDebug { "$TAG remove: move ${index + 1}-$nSize to $index" }
-                    hashes.copyInto(
-                        destination = hashes,
-                        destinationOffset = index,
-                        startIndex = index + 1,
-                        endIndex = nSize + 1
-                    )
-                    array.copyInto(
-                        destination = array,
-                        destinationOffset = index,
-                        startIndex = index + 1,
-                        endIndex = nSize + 1
-                    )
-                }
-                array[nSize] = null
-            }
-            if (oSize != _size) {
-                throw ConcurrentModificationException()
-            }
-            _size = nSize
-        }
-        @Suppress("UNCHECKED_CAST")
-        return old as E
-    }
+    public fun removeAt(index: Int): E
 
     /**
      * Perform a [remove] of all values in [array]
+     *
      * @param array The array whose contents are to be removed.
      */
-    public fun removeAll(array: ArraySet<out E>): Boolean {
-        // TODO: If array is sufficiently large, a marking approach might be beneficial. In a first
-        //       pass, use the property that the sets are sorted by hash to make this linear passes
-        //       (except for hash collisions, which means worst case still n*m), then do one
-        //       collection pass into a new array. This avoids binary searches and excessive memcpy.
-        val n = array._size
-
-        // Note: ArraySet does not make thread-safety guarantees. So instead of OR-ing together all
-        //       the single results, compare size before and after.
-        val originalSize = _size
-        for (i in 0 until n) {
-            remove(array.valueAt(i))
-        }
-        return originalSize != _size
-    }
-
-    @Suppress("ArrayReturn")
-    public fun toArray(): Array<Any?> {
-        return array.copyOfRange(fromIndex = 0, toIndex = _size)
-    }
-
-    @Suppress("ArrayReturn")
-    public fun <T> toArray(array: Array<T>): Array<T> {
-        return if (array.size < _size) {
-            @Suppress("UNCHECKED_CAST")
-            this.array.copyOfRange(fromIndex = 0, toIndex = _size) as Array<T>
-        } else {
-            @Suppress("UNCHECKED_CAST")
-            this.array.copyInto(array as Array<Any?>, 0, 0, _size)
-            if (array.size > _size) {
-                array[_size] = null
-            }
-            array
-        }
-    }
+    public fun removeAll(array: ArraySet<out E>): Boolean
 
     /**
      * This implementation returns false if the object is not a set, or
@@ -477,70 +179,19 @@
      *
      * @see Any.equals
      */
-    override fun equals(other: Any?): Boolean {
-        if (this === other) {
-            return true
-        }
-        if (other is Set<*>) {
-            if (size != other.size) {
-                return false
-            }
-            try {
-                for (i in 0 until _size) {
-                    val mine = valueAt(i)
-                    if (!other.contains(mine)) {
-                        return false
-                    }
-                }
-            } catch (ignored: NullPointerException) {
-                return false
-            } catch (ignored: ClassCastException) {
-                return false
-            }
-            return true
-        }
-        return false
-    }
+    override fun equals(other: Any?): Boolean
 
     /**
      * @see Any.hashCode
      */
-    override fun hashCode(): Int {
-        val hashes = hashes
-        val s = _size
-        var result = 0
-        for (i in 0 until s) {
-            result += hashes[i]
-        }
-        return result
-    }
+    override fun hashCode(): Int
 
     /**
      * This implementation composes a string by iterating over its values. If
      * this set contains itself as a value, the string "(this Set)"
      * will appear in its place.
      */
-    override fun toString(): String {
-        if (isEmpty()) {
-            return "{}"
-        }
-
-        return buildString(capacity = _size * 14) {
-            append('{')
-            for (i in 0 until _size) {
-                if (i > 0) {
-                    append(", ")
-                }
-                val value = valueAt(i)
-                if (value !== this@ArraySet) {
-                    append(value)
-                } else {
-                    append("(this Set)")
-                }
-            }
-            append('}')
-        }
-    }
+    override fun toString(): String
 
     /**
      * Return a [MutableIterator] over all values in the set.
@@ -548,84 +199,430 @@
      * **Note:** this is a less efficient way to access the array contents compared to
      * looping from 0 until [size] and calling [valueAt].
      */
-    override fun iterator(): MutableIterator<E> =
-        ElementIterator()
-
-    private inner class ElementIterator : IndexBasedArrayIterator<E>(_size) {
-        override fun elementAt(index: Int): E =
-            valueAt(index)
-
-        override fun removeAt(index: Int) {
-            this@ArraySet.removeAt(index)
-        }
-    }
+    override fun iterator(): MutableIterator<E>
 
     /**
      * Determine if the array set contains all of the values in the given collection.
+     *
      * @param elements The collection whose contents are to be checked against.
      * @return Returns true if this array set contains a value for every entry
      * in [elements] else returns false.
      */
-    override fun containsAll(elements: Collection<E>): Boolean {
-        for (item in elements) {
-            if (!contains(item)) {
-                return false
-            }
-        }
-        return true
-    }
+    override fun containsAll(elements: Collection<E>): Boolean
 
     /**
      * Perform an [add] of all values in [elements]
+     *
      * @param elements The collection whose contents are to be retrieved.
      */
-    override fun addAll(elements: Collection<E>): Boolean {
-        ensureCapacity(_size + elements.size)
-        var added = false
-        for (value in elements) {
-            added = add(value) or added
-        }
-        return added
-    }
+    override fun addAll(elements: Collection<E>): Boolean
 
     /**
      * Remove all values in the array set that exist in the given collection.
+     *
      * @param elements The collection whose contents are to be used to remove values.
      * @return Returns true if any values were removed from the array set, else false.
      */
-    override fun removeAll(elements: Collection<E>): Boolean {
-        var removed = false
-        for (value in elements) {
-            removed = removed or remove(value)
-        }
-        return removed
-    }
+    override fun removeAll(elements: Collection<E>): Boolean
 
     /**
      * Remove all values in the array set that do **not** exist in the given collection.
+     *
      * @param elements The collection whose contents are to be used to determine which
      * values to keep.
      * @return Returns true if any values were removed from the array set, else false.
      */
-    override fun retainAll(elements: Collection<E>): Boolean {
-        var removed = false
-        for (i in _size - 1 downTo 0) {
-            if (array[i] !in elements) {
-                removeAt(i)
-                removed = true
+    override fun retainAll(elements: Collection<E>): Boolean
+}
+
+/**
+ * The minimum amount by which the capacity of a ArraySet will increase.
+ * This is tuned to be relatively space-efficient.
+ */
+internal const val ARRAY_SET_BASE_SIZE = 4
+
+internal fun <E> ArraySet<E>.binarySearchInternal(hash: Int): Int =
+    try {
+        binarySearch(hashes, _size, hash)
+    } catch (e: IndexOutOfBoundsException) {
+        throw ConcurrentModificationException()
+    }
+
+internal fun <E> ArraySet<E>.indexOf(key: Any?, hash: Int): Int {
+    val n = _size
+
+    // Important fast case: if nothing is in here, nothing to look for.
+    if (n == 0) {
+        return -1
+    }
+    val index = binarySearchInternal(hash)
+
+    // If the hash code wasn't found, then we have no entry for this key.
+    if (index < 0) {
+        return index
+    }
+
+    // If the key at the returned index matches, that's what we want.
+    if (key == array[index]) {
+        return index
+    }
+
+    // Search for a matching key after the index.
+    var end = index + 1
+    while (end < n && hashes[end] == hash) {
+        if (key == array[end]) {
+            return end
+        }
+        end++
+    }
+
+    // Search for a matching key before the index.
+    var i = index - 1
+    while (i >= 0 && hashes[i] == hash) {
+        if (key == array[i]) {
+            return i
+        }
+        i--
+    }
+
+    // Key not found -- return negative value indicating where a
+    // new entry for this key should go.  We use the end of the
+    // hash chain to reduce the number of array entries that will
+    // need to be copied when inserting.
+    return end.inv()
+}
+
+internal fun <E> ArraySet<E>.indexOfNull(): Int = indexOf(key = null, hash = 0)
+
+internal fun <E> ArraySet<E>.allocArrays(size: Int) {
+    hashes = IntArray(size)
+    array = arrayOfNulls(size)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.clearInternal() {
+    if (_size != 0) {
+        hashes = EMPTY_INTS
+        array = EMPTY_OBJECTS
+        _size = 0
+    }
+    @Suppress("KotlinConstantConditions")
+    if (_size != 0) {
+        throw ConcurrentModificationException()
+    }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.ensureCapacityInternal(minimumCapacity: Int) {
+    val oSize: Int = _size
+    if (hashes.size < minimumCapacity) {
+        val ohashes = hashes
+        val oarray = array
+        allocArrays(minimumCapacity)
+        if (_size > 0) {
+            ohashes.copyInto(destination = hashes, endIndex = _size)
+            oarray.copyInto(destination = array, endIndex = _size)
+        }
+    }
+    if (_size != oSize) {
+        throw ConcurrentModificationException()
+    }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.containsInternal(element: E): Boolean {
+    return indexOf(element) >= 0
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.indexOfInternal(key: Any?): Int {
+    return if (key == null) indexOfNull() else indexOf(key = key, hash = key.hashCode())
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.valueAtInternal(index: Int): E {
+    @Suppress("UNCHECKED_CAST")
+    return array[index] as E
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.isEmptyInternal(): Boolean {
+    return _size <= 0
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.addInternal(element: E): Boolean {
+    val oSize = _size
+    val hash: Int
+    var index: Int
+    if (element == null) {
+        hash = 0
+        index = indexOfNull()
+    } else {
+        hash = element.hashCode()
+        index = indexOf(element, hash)
+    }
+
+    if (index >= 0) {
+        return false
+    }
+
+    index = index.inv()
+    if (oSize >= hashes.size) {
+        val n =
+            when {
+                oSize >= ARRAY_SET_BASE_SIZE * 2 -> oSize + (oSize shr 1)
+                oSize >= ARRAY_SET_BASE_SIZE -> ARRAY_SET_BASE_SIZE * 2
+                else -> ARRAY_SET_BASE_SIZE
+            }
+
+        val ohashes = hashes
+        val oarray = array
+        allocArrays(n)
+
+        if (oSize != _size) {
+            throw ConcurrentModificationException()
+        }
+
+        if (hashes.isNotEmpty()) {
+            ohashes.copyInto(destination = hashes, endIndex = ohashes.size)
+            oarray.copyInto(destination = array, endIndex = oarray.size)
+        }
+    }
+
+    if (index < oSize) {
+        hashes.copyInto(
+            destination = hashes,
+            destinationOffset = index + 1,
+            startIndex = index,
+            endIndex = oSize
+        )
+        array.copyInto(
+            destination = array,
+            destinationOffset = index + 1,
+            startIndex = index,
+            endIndex = oSize
+        )
+    }
+
+    if (oSize != _size || index >= hashes.size) {
+        throw ConcurrentModificationException()
+    }
+
+    hashes[index] = hash
+    array[index] = element
+    _size++
+    return true
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.addAllInternal(array: ArraySet<out E>) {
+    val n = array._size
+    ensureCapacity(_size + n)
+    if (_size == 0) {
+        if (n > 0) {
+            array.hashes.copyInto(destination = hashes, endIndex = n)
+            array.array.copyInto(destination = this.array, endIndex = n)
+            if (0 != _size) {
+                throw ConcurrentModificationException()
+            }
+            _size = n
+        }
+    } else {
+        for (i in 0 until n) {
+            add(array.valueAt(i))
+        }
+    }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.removeInternal(element: E): Boolean {
+    val index = indexOf(element)
+    if (index >= 0) {
+        removeAt(index)
+        return true
+    }
+    return false
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.removeAtInternal(index: Int): E {
+    val oSize = _size
+    val old = array[index]
+    if (oSize <= 1) {
+        // Now empty.
+        clear()
+    } else {
+        val nSize = oSize - 1
+        if (hashes.size > (ARRAY_SET_BASE_SIZE * 2) && (_size < hashes.size / 3)) {
+            // Shrunk enough to reduce size of arrays.  We don't allow it to
+            // shrink smaller than (ARRAY_SET_BASE_SIZE*2) to avoid flapping between
+            // that and ARRAY_SET_BASE_SIZE.
+            val n = when {
+                _size > ARRAY_SET_BASE_SIZE * 2 -> _size + (_size shr 1)
+                else -> ARRAY_SET_BASE_SIZE * 2
+            }
+            val ohashes = hashes
+            val oarray = array
+            allocArrays(n)
+            if (index > 0) {
+                ohashes.copyInto(destination = hashes, endIndex = index)
+                oarray.copyInto(destination = array, endIndex = index)
+            }
+            if (index < nSize) {
+                ohashes.copyInto(
+                    destination = hashes,
+                    destinationOffset = index,
+                    startIndex = index + 1,
+                    endIndex = nSize + 1
+                )
+                oarray.copyInto(
+                    destination = array,
+                    destinationOffset = index,
+                    startIndex = index + 1,
+                    endIndex = nSize + 1
+                )
+            }
+        } else {
+            if (index < nSize) {
+                hashes.copyInto(
+                    destination = hashes,
+                    destinationOffset = index,
+                    startIndex = index + 1,
+                    endIndex = nSize + 1
+                )
+                array.copyInto(
+                    destination = array,
+                    destinationOffset = index,
+                    startIndex = index + 1,
+                    endIndex = nSize + 1
+                )
+            }
+            array[nSize] = null
+        }
+        if (oSize != _size) {
+            throw ConcurrentModificationException()
+        }
+        _size = nSize
+    }
+    @Suppress("UNCHECKED_CAST")
+    return old as E
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.removeAllInternal(array: ArraySet<out E>): Boolean {
+    // TODO: If array is sufficiently large, a marking approach might be beneficial. In a first
+    //       pass, use the property that the sets are sorted by hash to make this linear passes
+    //       (except for hash collisions, which means worst case still n*m), then do one
+    //       collection pass into a new array. This avoids binary searches and excessive memcpy.
+    val n = array._size
+
+    // Note: ArraySet does not make thread-safety guarantees. So instead of OR-ing together all
+    //       the single results, compare size before and after.
+    val originalSize = _size
+    for (i in 0 until n) {
+        remove(array.valueAt(i))
+    }
+    return originalSize != _size
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.equalsInternal(other: Any?): Boolean {
+    if (this === other) {
+        return true
+    }
+    if (other is Set<*>) {
+        if (size != other.size) {
+            return false
+        }
+        try {
+            for (i in 0 until _size) {
+                val mine = valueAt(i)
+                if (!other.contains(mine)) {
+                    return false
+                }
+            }
+        } catch (ignored: NullPointerException) {
+            return false
+        } catch (ignored: ClassCastException) {
+            return false
+        }
+        return true
+    }
+    return false
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.hashCodeInternal(): Int {
+    val hashes = hashes
+    val s = _size
+    var result = 0
+    for (i in 0 until s) {
+        result += hashes[i]
+    }
+    return result
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.toStringInternal(): String {
+    if (isEmpty()) {
+        return "{}"
+    }
+
+    return buildString(capacity = _size * 14) {
+        append('{')
+        for (i in 0 until _size) {
+            if (i > 0) {
+                append(", ")
+            }
+            val value = valueAt(i)
+            if (value !== this@toStringInternal) {
+                append(value)
+            } else {
+                append("(this Set)")
             }
         }
-        return removed
+        append('}')
     }
+}
 
-    private companion object {
-        private const val DEBUG = false
-        private const val TAG = "ArraySet"
-
-        /**
-         * The minimum amount by which the capacity of a ArraySet will increase.
-         * This is tuned to be relatively space-efficient.
-         */
-        private const val BASE_SIZE = 4
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.containsAllInternal(elements: Collection<E>): Boolean {
+    for (item in elements) {
+        if (!contains(item)) {
+            return false
+        }
     }
+    return true
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.addAllInternal(elements: Collection<E>): Boolean {
+    ensureCapacity(_size + elements.size)
+    var added = false
+    for (value in elements) {
+        added = add(value) or added
+    }
+    return added
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.removeAllInternal(elements: Collection<E>): Boolean {
+    var removed = false
+    for (value in elements) {
+        removed = removed or remove(value)
+    }
+    return removed
+}
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun <E> ArraySet<E>.retainAllInternal(elements: Collection<E>): Boolean {
+    var removed = false
+    for (i in _size - 1 downTo 0) {
+        if (array[i] !in elements) {
+            removeAt(i)
+            removed = true
+        }
+    }
+    return removed
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ArraySetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ArraySetTest.kt
index 365694f..257a876 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ArraySetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ArraySetTest.kt
@@ -35,7 +35,6 @@
 import kotlinx.coroutines.runBlocking
 
 internal class ArraySetTest {
-
     private val set = ArraySet<String>()
 
     /**
diff --git a/collection/collection/src/jvmMain/java/androidx/collection/ArraySetJvmUtil.java b/collection/collection/src/jvmMain/java/androidx/collection/ArraySetJvmUtil.java
new file mode 100644
index 0000000..13642b6
--- /dev/null
+++ b/collection/collection/src/jvmMain/java/androidx/collection/ArraySetJvmUtil.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection;
+
+import java.lang.reflect.Array;
+
+class ArraySetJvmUtil {
+    private ArraySetJvmUtil() {
+    }
+
+    // Necessary to implement in Java to allow allocating a typed array without a callback for
+    // initialization. We also need to ignore the nullity of the type in order to null out the
+    // (n+1)'th item for behavior compatibility.
+    @SuppressWarnings("unchecked")
+    static <T> T[] resizeForToArray(T[] destination, int size) {
+        if (destination.length < size) {
+            return (T[]) Array.newInstance(destination.getClass().getComponentType(), size);
+        } else {
+            if (destination.length > size) {
+                destination[size] = null;
+            }
+            return destination;
+        }
+    }
+}
diff --git a/collection/collection/src/jvmMain/kotlin/androidx/collection/ArraySet.jvm.kt b/collection/collection/src/jvmMain/kotlin/androidx/collection/ArraySet.jvm.kt
new file mode 100644
index 0000000..e804ff1
--- /dev/null
+++ b/collection/collection/src/jvmMain/kotlin/androidx/collection/ArraySet.jvm.kt
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection
+
+import androidx.collection.internal.EMPTY_INTS
+import androidx.collection.internal.EMPTY_OBJECTS
+
+/**
+ * ArraySet is a generic set data structure that is designed to be more memory efficient than a
+ * traditional [HashSet].  The design is very similar to
+ * [ArrayMap], with all of the caveats described there.  This implementation is
+ * separate from ArrayMap, however, so the Object array contains only one item for each
+ * entry in the set (instead of a pair for a mapping).
+ *
+ * Note that this implementation is not intended to be appropriate for data structures
+ * that may contain large numbers of items.  It is generally slower than a traditional
+ * HashSet, since lookups require a binary search and adds and removes require inserting
+ * and deleting entries in the array.  For containers holding up to hundreds of items,
+ * the performance difference is not significant, less than 50%.
+ *
+ * Because this container is intended to better balance memory use, unlike most other
+ * standard Java containers it will shrink its array as items are removed from it.  Currently
+ * you have no control over this shrinking -- if you set a capacity and then remove an
+ * item, it may reduce the capacity to better match the current size.  In the future an
+ * explicit call to set the capacity should turn off this aggressive shrinking behavior.
+ *
+ * This structure is **NOT** thread-safe.
+ *
+ * @constructor Creates a new empty ArraySet. The default capacity of an array map is 0, and
+ * will grow once items are added to it.
+ */
+public actual class ArraySet<E>
+// TODO(b/237405792): Default value for optional argument is required here to workaround Metalava's
+//  lack of support for expect / actual.
+@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
+// TODO(b/237405286): @JvmOverloads is redundant in this actual, but is necessary here to workaround
+//  Metalava's lack of support for expect / actual.
+@JvmOverloads actual constructor(capacity: Int = 0) : MutableCollection<E>, MutableSet<E> {
+    internal actual var hashes: IntArray = EMPTY_INTS
+    internal actual var array: Array<Any?> = EMPTY_OBJECTS
+
+    internal actual var _size = 0
+    actual override val size: Int
+        get() = _size
+
+    /**
+     * Create a new ArraySet with the mappings from the given ArraySet.
+     */
+    public actual constructor(set: ArraySet<out E>?) : this(capacity = 0) {
+        if (set != null) {
+            addAll(set)
+        }
+    }
+
+    /**
+     * Create a new ArraySet with the mappings from the given [Collection].
+     */
+    public actual constructor(set: Collection<E>?) : this(capacity = 0) {
+        if (set != null) {
+            addAll(set)
+        }
+    }
+
+    /**
+     * Create a new ArraySet with items from the given array.
+     */
+    public actual constructor(array: Array<out E>?) : this(capacity = 0) {
+        if (array != null) {
+            for (value in array) {
+                add(value)
+            }
+        }
+    }
+
+    init {
+        if (capacity > 0) {
+            allocArrays(capacity)
+        }
+    }
+
+    /**
+     * Make the array map empty.  All storage is released.
+     *
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    actual override fun clear() {
+        clearInternal()
+    }
+
+    /**
+     * Ensure the array map can hold at least [minimumCapacity]
+     * items.
+     *
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun ensureCapacity(minimumCapacity: Int) {
+        ensureCapacityInternal(minimumCapacity)
+    }
+
+    /**
+     * Check whether a value exists in the set.
+     *
+     * @param element The value to search for.
+     * @return Returns true if the value exists, else false.
+     */
+    actual override operator fun contains(element: E): Boolean {
+        return containsInternal(element)
+    }
+
+    /**
+     * Returns the index of a value in the set.
+     *
+     * @param key The value to search for.
+     * @return Returns the index of the value if it exists, else a negative integer.
+     */
+    public actual fun indexOf(key: Any?): Int {
+        return indexOfInternal(key)
+    }
+
+    /**
+     * Return the value at the given index in the array.
+     *
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return Returns the value stored at the given index.
+     */
+    public actual fun valueAt(index: Int): E {
+        return valueAtInternal(index)
+    }
+
+    /**
+     * Return `true` if the array map contains no items.
+     */
+    actual override fun isEmpty(): Boolean {
+        return isEmptyInternal()
+    }
+
+    /**
+     * Adds the specified object to this set. The set is not modified if it
+     * already contains the object.
+     *
+     * @param element the object to add.
+     * @return `true` if this set is modified, `false` otherwise.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    actual override fun add(element: E): Boolean {
+        return addInternal(element)
+    }
+
+    /**
+     * Perform a [add] of all values in [array]
+     *
+     * @param array The array whose contents are to be retrieved.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun addAll(array: ArraySet<out E>) {
+        addAllInternal(array)
+    }
+
+    /**
+     * Removes the specified object from this set.
+     *
+     * @param element the object to remove.
+     * @return `true` if this set was modified, `false` otherwise.
+     */
+    actual override fun remove(element: E): Boolean {
+        return removeInternal(element)
+    }
+
+    /**
+     * Remove the key/value mapping at the given index.
+     *
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return Returns the value that was stored at this index.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun removeAt(index: Int): E {
+        return removeAtInternal(index)
+    }
+
+    /**
+     * Perform a [remove] of all values in [array]
+     *
+     * @param array The array whose contents are to be removed.
+     */
+    public actual fun removeAll(array: ArraySet<out E>): Boolean {
+        return removeAllInternal(array)
+    }
+
+    @Suppress("ArrayReturn")
+    public fun toArray(): Array<Any?> {
+        return array.copyOfRange(fromIndex = 0, toIndex = _size)
+    }
+
+    @Suppress("ArrayReturn")
+    public fun <T> toArray(array: Array<T>): Array<T> {
+        val result = ArraySetJvmUtil.resizeForToArray(array, _size)
+
+        @Suppress("UNCHECKED_CAST")
+        this.array.copyInto(result as Array<Any?>, 0, 0, _size)
+        return result
+    }
+
+    /**
+     * This implementation returns false if the object is not a set, or
+     * if the sets have different sizes.  Otherwise, for each value in this
+     * set, it checks to make sure the value also exists in the other set.
+     * If any value doesn't exist, the method returns false; otherwise, it
+     * returns true.
+     *
+     * @see Any.equals
+     */
+    actual override fun equals(other: Any?): Boolean {
+        return equalsInternal(other)
+    }
+
+    /**
+     * @see Any.hashCode
+     */
+    actual override fun hashCode(): Int {
+        return hashCodeInternal()
+    }
+
+    /**
+     * This implementation composes a string by iterating over its values. If
+     * this set contains itself as a value, the string "(this Set)"
+     * will appear in its place.
+     */
+    actual override fun toString(): String {
+        return toStringInternal()
+    }
+
+    /**
+     * Return a [MutableIterator] over all values in the set.
+     *
+     * **Note:** this is a less efficient way to access the array contents compared to
+     * looping from 0 until [size] and calling [valueAt].
+     */
+    actual override fun iterator(): MutableIterator<E> = ElementIterator()
+
+    private inner class ElementIterator : IndexBasedArrayIterator<E>(_size) {
+        override fun elementAt(index: Int): E = valueAt(index)
+
+        override fun removeAt(index: Int) {
+            this@ArraySet.removeAt(index)
+        }
+    }
+
+    /**
+     * Determine if the array set contains all of the values in the given collection.
+     *
+     * @param elements The collection whose contents are to be checked against.
+     * @return Returns true if this array set contains a value for every entry
+     * in [elements] else returns false.
+     */
+    actual override fun containsAll(elements: Collection<E>): Boolean {
+        return containsAllInternal(elements)
+    }
+
+    /**
+     * Perform an [add] of all values in [elements]
+     *
+     * @param elements The collection whose contents are to be retrieved.
+     */
+    actual override fun addAll(elements: Collection<E>): Boolean {
+        return addAllInternal(elements)
+    }
+
+    /**
+     * Remove all values in the array set that exist in the given collection.
+     *
+     * @param elements The collection whose contents are to be used to remove values.
+     * @return Returns true if any values were removed from the array set, else false.
+     */
+    actual override fun removeAll(elements: Collection<E>): Boolean {
+        return removeAllInternal(elements)
+    }
+
+    /**
+     * Remove all values in the array set that do **not** exist in the given collection.
+     *
+     * @param elements The collection whose contents are to be used to determine which
+     * values to keep.
+     * @return Returns true if any values were removed from the array set, else false.
+     */
+    actual override fun retainAll(elements: Collection<E>): Boolean {
+        return retainAllInternal(elements)
+    }
+}
diff --git a/collection/collection/src/jvmTest/kotlin/androidx/collection/ArraySetJvmTest.kt b/collection/collection/src/jvmTest/kotlin/androidx/collection/ArraySetJvmTest.kt
new file mode 100644
index 0000000..df77ccc
--- /dev/null
+++ b/collection/collection/src/jvmTest/kotlin/androidx/collection/ArraySetJvmTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection
+
+import kotlin.test.assertNull
+import org.junit.Test
+
+class ArraySetJvmTest {
+
+    @Test
+    fun toArray_emptyTypedDestination() {
+        val set = ArraySet<Int>()
+        for (i in 0..5) {
+            set.add(i)
+        }
+
+        // Forces casting, otherwise may not pick up certain failures. Typing just the destination
+        // array or return type is not sufficient to test on JVM.
+        @Suppress("UNUSED_VARIABLE")
+        val result: Array<Int> = set.toArray(emptyArray())
+    }
+
+    @Test
+    fun toArray_nullsLastElement() {
+        val set = ArraySet<Int>()
+        for (i in 0..4) {
+            set.add(i)
+        }
+
+        val result: Array<Int> = set.toArray(Array(10) { -1 })
+        assertNull(result[5])
+    }
+}
\ No newline at end of file
diff --git a/collection/collection/src/nativeMain/kotlin/androidx/collection/ArraySet.native.kt b/collection/collection/src/nativeMain/kotlin/androidx/collection/ArraySet.native.kt
new file mode 100644
index 0000000..9c7be56
--- /dev/null
+++ b/collection/collection/src/nativeMain/kotlin/androidx/collection/ArraySet.native.kt
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection
+
+import androidx.collection.internal.EMPTY_INTS
+import androidx.collection.internal.EMPTY_OBJECTS
+
+/**
+ * ArraySet is a generic set data structure that is designed to be more memory efficient than a
+ * traditional [HashSet].  The design is very similar to
+ * [ArrayMap], with all of the caveats described there.  This implementation is
+ * separate from ArrayMap, however, so the Object array contains only one item for each
+ * entry in the set (instead of a pair for a mapping).
+ *
+ * Note that this implementation is not intended to be appropriate for data structures
+ * that may contain large numbers of items.  It is generally slower than a traditional
+ * HashSet, since lookups require a binary search and adds and removes require inserting
+ * and deleting entries in the array.  For containers holding up to hundreds of items,
+ * the performance difference is not significant, less than 50%.
+ *
+ * Because this container is intended to better balance memory use, unlike most other
+ * standard Java containers it will shrink its array as items are removed from it.  Currently
+ * you have no control over this shrinking -- if you set a capacity and then remove an
+ * item, it may reduce the capacity to better match the current size.  In the future an
+ * explicit call to set the capacity should turn off this aggressive shrinking behavior.
+ *
+ * This structure is **NOT** thread-safe.
+ *
+ * @constructor Creates a new empty ArraySet. The default capacity of an array map is 0, and
+ * will grow once items are added to it.
+ */
+public actual class ArraySet<E> actual constructor(
+    capacity: Int
+) : MutableCollection<E>, MutableSet<E> {
+
+    internal actual var hashes: IntArray = EMPTY_INTS
+    internal actual var array: Array<Any?> = EMPTY_OBJECTS
+
+    internal actual var _size = 0
+    actual override val size: Int
+        get() = _size
+
+    /**
+     * Create a new ArraySet with the mappings from the given ArraySet.
+     */
+    public actual constructor(set: ArraySet<out E>?) : this(capacity = 0) {
+        if (set != null) {
+            addAll(set)
+        }
+    }
+
+    /**
+     * Create a new ArraySet with the mappings from the given [Collection].
+     */
+    public actual constructor(set: Collection<E>?) : this(capacity = 0) {
+        if (set != null) {
+            addAll(set)
+        }
+    }
+
+    /**
+     * Create a new ArraySet with items from the given array.
+     */
+    public actual constructor(array: Array<out E>?) : this(capacity = 0) {
+        if (array != null) {
+            for (value in array) {
+                add(value)
+            }
+        }
+    }
+
+    init {
+        if (capacity > 0) {
+            allocArrays(capacity)
+        }
+    }
+
+    /**
+     * Make the array map empty.  All storage is released.
+     *
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    actual override fun clear() {
+        clearInternal()
+    }
+
+    /**
+     * Ensure the array map can hold at least [minimumCapacity]
+     * items.
+     *
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun ensureCapacity(minimumCapacity: Int) {
+        ensureCapacityInternal(minimumCapacity)
+    }
+
+    /**
+     * Check whether a value exists in the set.
+     *
+     * @param element The value to search for.
+     * @return Returns true if the value exists, else false.
+     */
+    actual override operator fun contains(element: E): Boolean {
+        return containsInternal(element)
+    }
+
+    /**
+     * Returns the index of a value in the set.
+     *
+     * @param key The value to search for.
+     * @return Returns the index of the value if it exists, else a negative integer.
+     */
+    public actual fun indexOf(key: Any?): Int {
+        return indexOfInternal(key)
+    }
+
+    /**
+     * Return the value at the given index in the array.
+     *
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return Returns the value stored at the given index.
+     */
+    public actual fun valueAt(index: Int): E {
+        return valueAtInternal(index)
+    }
+
+    /**
+     * Return `true` if the array map contains no items.
+     */
+    actual override fun isEmpty(): Boolean {
+        return isEmptyInternal()
+    }
+
+    /**
+     * Adds the specified object to this set. The set is not modified if it
+     * already contains the object.
+     *
+     * @param element the object to add.
+     * @return `true` if this set is modified, `false` otherwise.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    actual override fun add(element: E): Boolean {
+        return addInternal(element)
+    }
+
+    /**
+     * Perform a [add] of all values in [array]
+     *
+     * @param array The array whose contents are to be retrieved.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun addAll(array: ArraySet<out E>) {
+        addAllInternal(array)
+    }
+
+    /**
+     * Removes the specified object from this set.
+     *
+     * @param element the object to remove.
+     * @return `true` if this set was modified, `false` otherwise.
+     */
+    actual override fun remove(element: E): Boolean {
+        return removeInternal(element)
+    }
+
+    /**
+     * Remove the key/value mapping at the given index.
+     *
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return Returns the value that was stored at this index.
+     * @throws ConcurrentModificationException if concurrent modifications detected.
+     */
+    public actual fun removeAt(index: Int): E {
+        return removeAtInternal(index)
+    }
+
+    /**
+     * Perform a [remove] of all values in [array]
+     *
+     * @param array The array whose contents are to be removed.
+     */
+    public actual fun removeAll(array: ArraySet<out E>): Boolean {
+        return removeAllInternal(array)
+    }
+
+    /**
+     * This implementation returns false if the object is not a set, or
+     * if the sets have different sizes.  Otherwise, for each value in this
+     * set, it checks to make sure the value also exists in the other set.
+     * If any value doesn't exist, the method returns false; otherwise, it
+     * returns true.
+     *
+     * @see Any.equals
+     */
+    actual override fun equals(other: Any?): Boolean {
+        return equalsInternal(other)
+    }
+
+    /**
+     * @see Any.hashCode
+     */
+    actual override fun hashCode(): Int {
+        return hashCodeInternal()
+    }
+
+    /**
+     * This implementation composes a string by iterating over its values. If
+     * this set contains itself as a value, the string "(this Set)"
+     * will appear in its place.
+     */
+    actual override fun toString(): String {
+        return toStringInternal()
+    }
+
+    /**
+     * Return a [MutableIterator] over all values in the set.
+     *
+     * **Note:** this is a less efficient way to access the array contents compared to
+     * looping from 0 until [size] and calling [valueAt].
+     */
+    actual override fun iterator(): MutableIterator<E> = ElementIterator()
+
+    private inner class ElementIterator : IndexBasedArrayIterator<E>(_size) {
+        override fun elementAt(index: Int): E = valueAt(index)
+
+        override fun removeAt(index: Int) {
+            this@ArraySet.removeAt(index)
+        }
+    }
+
+    /**
+     * Determine if the array set contains all of the values in the given collection.
+     *
+     * @param elements The collection whose contents are to be checked against.
+     * @return Returns true if this array set contains a value for every entry
+     * in [elements] else returns false.
+     */
+    actual override fun containsAll(elements: Collection<E>): Boolean {
+        return containsAllInternal(elements)
+    }
+
+    /**
+     * Perform an [add] of all values in [elements]
+     *
+     * @param elements The collection whose contents are to be retrieved.
+     */
+    actual override fun addAll(elements: Collection<E>): Boolean {
+        return addAllInternal(elements)
+    }
+
+    /**
+     * Remove all values in the array set that exist in the given collection.
+     *
+     * @param elements The collection whose contents are to be used to remove values.
+     * @return Returns true if any values were removed from the array set, else false.
+     */
+    actual override fun removeAll(elements: Collection<E>): Boolean {
+        return removeAll(elements)
+    }
+
+    /**
+     * Remove all values in the array set that do **not** exist in the given collection.
+     *
+     * @param elements The collection whose contents are to be used to determine which
+     * values to keep.
+     * @return Returns true if any values were removed from the array set, else false.
+     */
+    actual override fun retainAll(elements: Collection<E>): Boolean {
+        return retainAllInternal(elements)
+    }
+}
