Arrays en Kotlin

Arrays en Kotlin

Como ya vimos cuando nos referimos a los tipos básicos de datos en Kotlin, básicamente un array es un contenedor o colección de tamaño fijo de elementos homogéneos (del mismo tipo) que se almacenan en una ubicación de memoria continua; su tamaño se establece en el momento de la declaración y se mantiene fijo durante el programa.

En Kotlin un Array es una clase con una propiedad que define su tamaño (el número de elementos) y con funciones get y set y algunos otros métodos. En esta entrada vamos a repasar aspectos como su declaración, inicialización y acceso a sus elementos.

Hay varias formas para crear un array en Kotlin, vamos a ver algunas de las más habituales:

1. Con las funciones arrayOf() y arrayOfNulls():
var miArrayEnteros = arrayOf<Int>(1, 10, 4, 6, 15)
var miArrayString = arrayOf<String>("amarillo", "verde", "rojo", "blanco","negro")

// con tipos inferidos
var numeros = arrayOf(1, 2, 3, 4, 5)
var animales = arrayOf("gato", "perro", "elefante", "tigre")
Observa que cuando infieres el tipo de los elementos puedes pasar valores de distinto tipo (no recomendable) a la función arrayOf, y esto es así porque se infiere que es un array de objetos:
var arrayMix = arrayOf(1, true, 3, "Hola", 'A') // array de objetos
// matriz de enteros de tamaño 5 con valores nulos
var array = arrayOfNulls<Int>(5)

2. A partir del tipo de dato primitivo de sus elementos:
var arrayEnteros = intArrayOf(5, 3, 4, 5)

var arrayFloat = floatArrayOf(5.3f, 3.2f, 4.3f, 5.4f)

var arrayDecimales = doubleArrayOf(3.1, 3.14, 3.141, 3.145)

var arrayCaracter = charArrayOf('a', 'b', 'c', 'd')

3. Usando el constructor de la clase Array con dos parámetros: el tamaño del array y la inicialización, que es una función en forma de expresión lambda que toma el índice del array como un argumento y devuelve el elemento que se insertará en ese índice.
// crea un array con 5 elementos inicializados con valor 0
var array = Array<Int>(5, { index -> 0 })

// lo mismo de manera más concisa
var array = Array<Int>(5, { 0 })

// y la versión mínima
val array = Array(5) { 0 }

// crea una matriz de tamaño 5 inicializado por su índice:
// el índice 0 se inicializará con valor 0 y así sucesivamente
var arr = Array<Int>(5, { it })

// valores inicializados con el cuadrado de sus respectivos índices
var arr = Array<Int>(5, { it * it })

// crea un array con 6 elementos de tipo String vacíos
var arrayString: Array<String> = Array(6) { "" }
var i = 0
for (a in "KOTLIN") {
    arrayString[i] = a.toString()
    i++
}
for (a in arrayString) print(a) // KOTLIN

4. Combinando el tipo de datos primitivo y el constructor:
var arr= IntArray(5, { it * it })   // para valores enteros
En el momento de declararlo podemos utilizar solo la propiedad del tamaño y posteriormente inicializar los elementos, aunque realmente se han creado con valores por defecto:
var arr = IntArray(5)

for (a in arr) print(a) // 00000

for(i in (0..4)) arr[i] = i

for (a in arr) print(a) // 01234
Realmente IntArray(), FloatArray(), ByteArray(), ShortArray() y similares son clases distintas a la clase Array pero contienen los mismos métodos y propiedades y se usan de manera similar.

Vamos a ver un ejemplo de un programa que declara e inicializa matrices con algunos de estos métodos:
fun main(args: Array<String>) {

    var arr = arrayOf(5, 3, 4, 5)
    print("0. arrayOf():")
    for(a in arr) print(" $a")

    var arr1 = arrayOfNulls<Int>(5)
    print("\n1. arrayOfNuls():")
    for (a in arr1) print(" $a")

    var arr2 = intArrayOf(5, 3, 4, 5)
    print("\n2. intArrayOf():")
    for (a in arr2) print(" $a")

    var arr3 = doubleArrayOf(5.3, 3.2, 4.3, 5.4)
    print("\n3. doubleArrayOf():")
    for (a in arr3) print(" $a")

    var arr4 = Array<Int>(5, { 0 })
    print("\n4. Array<Int>() inicializado con 0:")
    for (a in arr4) print(" $a")

    var arr5 = Array<Int>(5, { it * it })
    print("\n5. Array<Int>() con el cuadrado del índice:")
    for (a in arr5) print(" $a")

    var arr6 = IntArray(5, { it * it })
    print("\n6. IntArray() con el cuadrado del índice:")
    for (a in arr6) print(" $a")
}
0. arrayOf(): 5 3 4 5
1. arrayOfNuls(): null null null null null
2. intArrayOf(): 5 3 4 5
3. doubleArrayOf(): 5.3 3.2 4.3 5.4
4. Array() inicializado con 0: 0 0 0 0 0
5. Array() con el cuadrado del índice: 0 1 4 9 16
6. IntArray() con el cuadrado del índice: 0 1 4 9 16

Las funciones get y set (ver Métodos Get y Set de las propiedades de clase) utilizan el índice de los elementos para, respectivamente, devolver el valor de un elemento y establecer o cambiar su valor. Estos métodos se utilizan invocando el nombre del array seguido por el índice del elemento entre corchetes:
var arrayLetras = arrayOf('K', 'A', 'T', 'L', 'I', 'N')
println(arrayLetras[1]) // A
arrayLetras[1] = 'O'
println(arrayLetras[1]) // O
En el ejemplo anterior podemos utilizar explícitamente las funciones get y set de esta manera:
println(arrayLetras.get(1)) // similar a println(arrayLetras[1])
arrayLetras.set(1, 'O')     // similar a arrayLetras[1] = 'O'

Tenemos varias maneras de recorrer un array para acceder a sus elementos generando bucles de repetición, ya sea con la estructura de repetición for o con métodos propios de la clase Array como forEach y forEachIndexed:
var miArray = arrayOf(1, 2, 3, 4)

for (a in miArray) print(a)

for (i in miArray.indices) print(miArray[i])

for(i in (0..miArray.size-1)) print(miArray[i])

for(i in (0..miArray.lastIndex)) print(miArray[i])

for (i in 0 until miArray.size) print(miArray[i])

// forEach acepta un solo parámetro para accede a cada elemento
miArray.forEach( { a -> print(a) } )

miArray.forEach( { print(it) } )

// con la función withIndex accedemos al índice y al elemento
for ((index, arg) in miArray.withIndex()) println("$index: $arg")

// forEachIndexed acepta dos parámetros: el índice y el elemento
miArray.forEachIndexed( { a, i -> print("Indice $a = "); println(i) } )

Es posible crear arrays multidimensionales, es decir arrays que tienen como elementos otros arrays, y se pueden recorrer utilizando bucles anidados:
// array 3 x 3
var a = arrayOf(arrayOf(1,2,3), arrayOf(4,5,6), arrayOf(7,8,9))

for (i in a.indices) {
    for (j in a[i].indices)
        print(a[i][j]) // 123456789
}
También podemos crear un array 100 x 100 así:
// array de 100 arrays, cada uno con 100 elementos con valor 0
var b = Array(100, { Array(100, { 0 }) })
En caso de crear un array multidimensional de la siguiente manera:
var col = arrayOf(1,2,3)
var a = arrayOf(col, col, col)
hay que tener en cuenta que los tres arrays son el mismo objeto por lo que al cambiar uno de ellos el resto cambiará al mismo valor:
var col = arrayOf(1,2,3)
var a = arrayOf(col, col, col)
a[0][0] = 4

for (i in a.indices) {
    for (j in a[i].indices)
        print(a[i][j]) // 423423423 (no 423123123)
}

Comentarios

Entradas populares

I/O: entrada y salida de datos en consola

Recursos gratis para aprender Kotlin

Lectura y escritura de archivos