Skip to content

Commit d8651a0

Browse files
fzhinkinSpace Team
authored andcommitted
[stdlib] Fix ArrayDeque.indexOf and lastIndexOf
There are two related bugs: - KT-80390: ArrayDeque.indexOf(null) returns some index when a deque had some elements, but later was cleaned - KT-80661: ArrayDeque.lastIndexOf returns -1 when the internal storage is full (i.e. head == internalIndex(size)) In both cases, we have to be more careful when scanning the internal storage if head == internalIndex(size). ^KT-80390 fixed ^KT-80661 fixed Merge-request: KT-MR-23363 Merged-by: Filipp Zhinkin <[email protected]>
1 parent 2afb699 commit d8651a0

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

libraries/stdlib/src/kotlin/collections/ArrayDeque.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
33
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
44
*/
55

@@ -393,7 +393,7 @@ public class ArrayDeque<E> : AbstractMutableList<E> {
393393
for (index in head until tail) {
394394
if (element == elementData[index]) return index - head
395395
}
396-
} else if (head >= tail) {
396+
} else if (isNotEmpty() && head >= tail) {
397397
for (index in head until elementData.size) {
398398
if (element == elementData[index]) return index - head
399399
}
@@ -412,7 +412,7 @@ public class ArrayDeque<E> : AbstractMutableList<E> {
412412
for (index in tail - 1 downTo head) {
413413
if (element == elementData[index]) return index - head
414414
}
415-
} else if (head > tail) {
415+
} else if (isNotEmpty() && head >= tail) {
416416
for (index in tail - 1 downTo 0) {
417417
if (element == elementData[index]) return index + elementData.size - head
418418
}

libraries/stdlib/test/collections/ArrayDequeTest.kt

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
33
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
44
*/
55

@@ -429,6 +429,63 @@ class ArrayDequeTest {
429429
(0..6).forEach { assertEquals(it, deque.indexOf(it - 4)) }
430430
assertEquals(-1, deque.indexOf(100))
431431
}
432+
433+
testArrayDeque { bufferSize, _, head, tail ->
434+
generateArrayDeque(head, tail, bufferSize).let { deque ->
435+
deque.forEachIndexed { index, element ->
436+
val actualIndex = deque.indexOf(element)
437+
if (actualIndex != index) {
438+
assertEquals(index, actualIndex, "indexOf($element) for $deque")
439+
}
440+
}
441+
}
442+
}
443+
}
444+
445+
@Test
446+
fun indexOfNull() {
447+
val deque = ArrayDeque<Int?>()
448+
assertEquals(-1, deque.indexOf(null))
449+
deque.addLast(42)
450+
assertEquals(-1, deque.indexOf(null))
451+
deque.clear()
452+
assertEquals(-1, deque.indexOf(null))
453+
}
454+
455+
@Test
456+
fun lastIndexOf() {
457+
// head < tail
458+
generateArrayDeque(0, 7).let { deque ->
459+
(0..6).forEach { assertEquals(it, deque.lastIndexOf(it)) }
460+
assertEquals(-1, deque.lastIndexOf(100))
461+
}
462+
463+
// head > tail
464+
generateArrayDeque(-4, 3).let { deque ->
465+
(0..6).forEach { assertEquals(it, deque.lastIndexOf(it - 4)) }
466+
assertEquals(-1, deque.lastIndexOf(100))
467+
}
468+
469+
testArrayDeque { bufferSize, _, head, tail ->
470+
generateArrayDeque(head, tail, bufferSize).let { deque ->
471+
deque.forEachIndexed { index, element ->
472+
val actualIndex = deque.lastIndexOf(element)
473+
if (actualIndex != index) {
474+
assertEquals(index, actualIndex, "lastIndexOf($element) for $deque")
475+
}
476+
}
477+
}
478+
}
479+
}
480+
481+
@Test
482+
fun lastIndexOfNull() {
483+
val deque = ArrayDeque<Int?>()
484+
assertEquals(-1, deque.lastIndexOf(null))
485+
deque.addLast(42)
486+
assertEquals(-1, deque.lastIndexOf(null))
487+
deque.clear()
488+
assertEquals(-1, deque.lastIndexOf(null))
432489
}
433490

434491
@Test
@@ -694,4 +751,4 @@ class ArrayDequeTest {
694751
deque.internalStructure { head, _ -> assertEquals(-2, head) } // deque min capacity is 10
695752
testContentEquals(arrayOf(-3, -2, -1, 1, 2, 3, 4, 5, 6, 7))
696753
}
697-
}
754+
}

0 commit comments

Comments
 (0)