Move ArrayDeque.newCapacity to AbstractList

This commit is contained in:
Abduqodiri Qurbonzoda
2023-05-30 21:54:19 +03:00
committed by Space Team
parent d8cfc79d92
commit 2ef50f8c34
6 changed files with 67 additions and 53 deletions
@@ -183,7 +183,7 @@ internal class ListBuilder<E> private constructor(
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ListBuilder
if (minCapacity < 0) throw OutOfMemoryError() // overflow
if (minCapacity > array.size) {
val newSize = ArrayDeque.newCapacity(array.size, minCapacity)
val newSize = AbstractList.newCapacity(array.size, minCapacity)
array = array.copyOfUninitializedElements(newSize)
}
}
@@ -148,7 +148,7 @@ actual class ArrayList<E> private constructor(
if (backingList != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList
if (minCapacity < 0) throw OutOfMemoryError() // overflow
if (minCapacity > backingArray.size) {
val newSize = ArrayDeque.newCapacity(backingArray.size, minCapacity)
val newSize = AbstractList.newCapacity(backingArray.size, minCapacity)
backingArray = backingArray.copyOfUninitializedElements(newSize)
}
}
@@ -133,6 +133,19 @@ public abstract class AbstractList<out E> protected constructor() : AbstractColl
}
}
private const val maxArraySize = Int.MAX_VALUE - 8
/** [oldCapacity] and [minCapacity] must be non-negative. */
internal fun newCapacity(oldCapacity: Int, minCapacity: Int): Int {
// overflow-conscious
var newCapacity = oldCapacity + (oldCapacity shr 1)
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity
if (newCapacity - maxArraySize > 0)
newCapacity = if (minCapacity > maxArraySize) Int.MAX_VALUE else maxArraySize
return newCapacity
}
internal fun orderedHashCode(c: Collection<*>): Int {
var hashCode = 1
for (e in c) {
@@ -63,7 +63,7 @@ public class ArrayDeque<E> : AbstractMutableList<E> {
return
}
val newCapacity = newCapacity(elementData.size, minCapacity)
val newCapacity = AbstractList.newCapacity(elementData.size, minCapacity)
copyElements(newCapacity)
}
@@ -560,18 +560,7 @@ public class ArrayDeque<E> : AbstractMutableList<E> {
internal companion object {
private val emptyElementData = emptyArray<Any?>()
private const val maxArraySize = Int.MAX_VALUE - 8
private const val defaultMinCapacity = 10
internal fun newCapacity(oldCapacity: Int, minCapacity: Int): Int {
// overflow-conscious
var newCapacity = oldCapacity + (oldCapacity shr 1)
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity
if (newCapacity - maxArraySize > 0)
newCapacity = if (minCapacity > maxArraySize) Int.MAX_VALUE else maxArraySize
return newCapacity
}
}
// For testing only
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.collections
import kotlin.random.Random
import kotlin.random.nextInt
import kotlin.test.*
class AbstractListTest {
@Suppress("INVISIBLE_MEMBER")
@Test
fun newCapacity() {
// oldCapacity < minCapacity < newCapacity
repeat(100) {
val oldCapacity = Random.nextInt(1 shl 30)
val newCapacity = oldCapacity + (oldCapacity shr 1)
val minCapacity = Random.nextInt(oldCapacity + 1 until newCapacity)
assertEquals(newCapacity, AbstractList.newCapacity(oldCapacity, minCapacity))
}
// oldCapacity < newCapacity < minCapacity
repeat(100) {
val oldCapacity = Random.nextInt(1 shl 30)
val newCapacity = oldCapacity + (oldCapacity shr 1)
val minCapacity = Random.nextInt(newCapacity..Int.MAX_VALUE)
assertEquals(minCapacity, AbstractList.newCapacity(oldCapacity, minCapacity))
}
// newCapacity overflow, oldCapacity < minCapacity <= maxArraySize
val maxArraySize = Int.MAX_VALUE - 8
repeat(100) {
val oldCapacity = Random.nextInt((1 shl 30) + (1 shl 29) until maxArraySize)
val minCapacity = Random.nextInt(oldCapacity..maxArraySize)
assertEquals(maxArraySize, AbstractList.newCapacity(oldCapacity, minCapacity))
}
// newCapacity overflow, minCapacity > maxArraySize
repeat(100) {
val oldCapacity = Random.nextInt((1 shl 30) + (1 shl 29)..maxArraySize)
val minCapacity = Random.nextInt(maxArraySize + 1..Int.MAX_VALUE)
assertEquals(Int.MAX_VALUE, AbstractList.newCapacity(oldCapacity, minCapacity))
}
}
}
@@ -608,45 +608,6 @@ class ArrayDequeTest {
}
}
@Suppress("INVISIBLE_MEMBER")
@Test
fun newCapacity() {
// oldCapacity < minCapacity < newCapacity
repeat(100) {
val oldCapacity = Random.nextInt(1 shl 30)
val newCapacity = oldCapacity + (oldCapacity shr 1)
val minCapacity = Random.nextInt(oldCapacity + 1 until newCapacity)
assertEquals(newCapacity, ArrayDeque.newCapacity(oldCapacity, minCapacity))
}
// oldCapacity < newCapacity < minCapacity
repeat(100) {
val oldCapacity = Random.nextInt(1 shl 30)
val newCapacity = oldCapacity + (oldCapacity shr 1)
val minCapacity = Random.nextInt(newCapacity..Int.MAX_VALUE)
assertEquals(minCapacity, ArrayDeque.newCapacity(oldCapacity, minCapacity))
}
// newCapacity overflow, oldCapacity < minCapacity <= maxArraySize
val maxArraySize = Int.MAX_VALUE - 8
repeat(100) {
val oldCapacity = Random.nextInt((1 shl 30) + (1 shl 29) until maxArraySize)
val minCapacity = Random.nextInt(oldCapacity..maxArraySize)
assertEquals(maxArraySize, ArrayDeque.newCapacity(oldCapacity, minCapacity))
}
// newCapacity overflow, minCapacity > maxArraySize
repeat(100) {
val oldCapacity = Random.nextInt((1 shl 30) + (1 shl 29)..maxArraySize)
val minCapacity = Random.nextInt(maxArraySize + 1..Int.MAX_VALUE)
assertEquals(Int.MAX_VALUE, ArrayDeque.newCapacity(oldCapacity, minCapacity))
}
}
@Suppress("INVISIBLE_MEMBER")
@Test
fun toArray() {