1

Is it possible in Kotlin to create a copy of a generic array with new size if I already have an instance of that array and pass a construction method for its items? I think about something like this:

fun <T> resize(arr: Array<T>, newSize: Int, creator: (Int) -> T): Array<T> {
    ...
}

Obviously I cannot call Array<T>(newSize) { i -> creator(i) } because the type T is not known at compile time. For efficicy reasons I do not want to use an inline function with a reified type. I also cannot use the arr.copyOf(newSize) method here because that would return an Array<T?>.

In Java I could use Arrays.copyOf(arr, newSize) even with a generic array because we don't have null safety here. But would this work in Kotlin as well? Or do you have any other ideas what I could do?

1
  • "For efficicy reasons I do not want to use an inline function with a reified type." Why? It should be more efficient by inlining creator. Commented Dec 5, 2018 at 7:35

2 Answers 2

3

I would just add an extension method to Array<T> for this. You can still rely on Arrays.copyOf under the hood, but before returning the value fill any remaining spaces with the result of the creator block:

fun <T> Array<T>.resize(newSize: Int, creator: (Int) -> T): Array<T> {
    val copiedArray = Arrays.copyOf(this, newSize)
    for (i in size until newSize) { copiedArray[i] = creator(i) }
    return copiedArray
}

For example:

val array = arrayOf("a", "b", "c")

// same: [a, b, c]
println("same: ${Arrays.toString(array.resize(3) { it.toString() })}")

// less: [a, b]
println("less: ${Arrays.toString(array.resize(2) { it.toString() })}")

// more: [a, b, c, 3, 4]
println("more: ${Arrays.toString(array.resize(5) { it.toString() })}")
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks that worked great :) Don't know Kotlin does not provide this by default
But this is only possible because I already have an instance of that array right? I could not use this method to create a completely new array of a generic type right?
Correct, but you can use the built-in function that @Sergey usedbelow for that -- e.g. Array(size) { index -> index.toString() }
0

I guess this will work:

fun <T> resize(arr: Array<T>, dest: Array<T>, creator: (Int) -> T): Array<T> {
    val list = arrayListOf<T>()
    // fill the list
    for (i in 0 until dest.size) {
        list.add(creator(i))
    }
    return list.toArray(dest)
}

fun callResize() {
    val arr = Array(5) { " " }
    val dest = Array(10) { "" }
    val creator = { i: Int -> "$i"}
    resize(arr, dest, creator)
}

The result is in the dest array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.