Move ArrayDeque.newCapacity to AbstractList
This commit is contained in:
committed by
Space Team
parent
d8cfc79d92
commit
2ef50f8c34
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user