is there a function which allows to remove last `n...
# getting-started
l
is there a function which allows to remove last
n
elements from a MutableList? I.e. equivalent of
dropLast(Int)
for
List
. Something like
MutableList.removeLast(Int)
c
Copy code
repeat(4) { list.removeLast() }
?
s
It might be more efficient with a sublist:
Copy code
fun MutableList<*>.removeLast(n: Int) {
    subList(size - n, size).clear()
}
c
@Sam depends on your list. As far as I know, all lists guarantee
O(1)
removeLast
. Not sure how predictable
subList(...).clear()
is
e
for
java.util.ArrayList
,
subList(size - 1n, size).clear()
calls
removeRange(size - n, size)
which is O(1)
that is better than repeated
removeLast()
which is O(n)
🙏 1
l
Thanks for your answers!
c
Well then the best solution is just to call
removeRange(size-4, size)
. It's also the easiest to read.
e
you can't call
removeRange
because it is
protected
c
Oh :/
l
I was kind of hoping that the standard library would just provide a single method/extension function for this.
e
it is also a method of
java.util.AbstractList
, not
kotlin.collections.MutableList
l
Although I just tested and actually
repeat(n) { list.removeLast() }
was faster
My program does read lines from text file as well (to process them), but the results are consistent (using the same text file): repeat removeLast(): 41-63 µs per function run subList clear: 67-81 µs per function run
function with `repeat removeLast()`:
Copy code
private fun executeMove(move: Move) {
    with(move) {
        val sourceStack = stacks[fromStack]
        val destinationStack = stacks[toStack]

        val crates = sourceStack.takeLast(numberOfCrates)
        repeat(numberOfCrates) { sourceStack.removeLast() }
        destinationStack.addAll(crates)
    }
}
function with `subList clear()`:
Copy code
private fun executeMove(move: Move) {
    with(move) {
        val sourceStack = stacks[fromStack]
        val destinationStack = stacks[toStack]

        val crates = sourceStack.takeLast(numberOfCrates)
        val sourceStackSize = sourceStack.size
        sourceStack.subList(sourceStackSize - numberOfCrates, sourceStackSize).clear()
        destinationStack.addAll(crates)
    }
}
(That's part of the solution to Advent of Code 2022 day 5)
👍 1
Both
sourceStack
and
destinationStack
are
ArrayDeque<Char>
Which implements
AbstractMutableList
I also must admit, that the
repeat { removeLast() }
is a bit more readable than
subList().clear()
e
I did a benchmark and it seems that for small
n
,
repeat(n) { removeLast() }
(probably due to no temporary objects) while for large
n
,
subList().clear()
is faster
👍 1
l
Yes, I was also suspecting the temporary object creation being the overhead in my case (n is usually between 1 and 20 in my program)
Thanks for checking!