Kotlin Language

Gli array

Come in altri linguaggi Kotlin ci mette a disposizione la possibilità di racchiudere uno o più elementi di un stesso tipo in una sequenza indicizzata. Questo "qualcosa" che racchiude gli elementi è proprio un array. Tenendo presente che il compilatore crea array Java veri e propri da passare alla JVM, cominciamo dicendo che in questo linguaggio abbiamo 3 modi per creare un array:
  • Con la funzione arrayOf  che crea un array avente come elementi gli argomenti passati alla funzione stessa
  • Tramite arrayOfNulls, che crea un array di element null e pu; accogliere solo elementi nullable
  • Tramite il classico costruttore Array.

 Il più immediato, forse solo in apparenza, è l'ultimo dei 3 che vediamo subito in azione.

  Esempio 6
1
2
3
4
fun main(args: Array<String>)
{
  val x = Array<Int>(10){0}
}

Come si vede è molto semplice. Array deve essere accompagnato da una funzione lambda, che vedremo, per inizializzare gli elementi, in questo caso sono tutti 0. Un altro esempio un po' più completo è il seguente:

  Esempio 6
1
2
3
4
5
6
fun main(args: Array<String>)
{
  val x = Array<Int>(10){x -> x *2}
  for (x1 in 0..x.size-1)
  println(x[x1])
}

Di passaggio, notiamo la proprietà size che esprime il numero di elementi dell'array. Esiste anche, che fornisce lo stesso risultato, il metodo count(). Avrete osservato anche che l'operatore [] è quello che permette di accedere ad un singolo elemento ed inooltre che gli indici che abbiamo preso in considerazione vanno da a size-1, ovvero da 0 a 9, essendoci 10 elementi. Gli array in Kotlin, pertanto, sono 0-based. Sempre di passaggio, anche se lo userete raramente, tenete presente che esiste anche il metodo get(indice) che restituisce l'elemento ad un certo indice, esempio

println(x.get(3))

Prima di proseguire nello studio di proprietà e metodi per lavorare sugli array, vediamo in azione arrayOf:

  Esempio 6
1
2
3
4
5
6
7
fun main(args: Array<String>)
{
  val arr01 = arrayOf(1,2,3)
  println(arr01[2])
  val arr02 = arrayOf('a', 'b', 'c')
  println(arr02[2])
}

Come si vede è molto semplice.
Kotlin dispone comunque anche di costruttori specifici per gli array con elementi appartenenti ai tipi base, interi, caratteri, byte, ecc.... che risultano particolarmente efficienti. Il nome di questi costruttori è semplice: IntArray, ByteArray, CharArray e via di seguito, che hanno una sintassi molto semplice, basta indicare il numero degli elementi tra parentesi, come nei due esempi qui di seguito:

val arr01 = IntArray(7)
val arr02 = CharArray(5)

che creano, rispettivamente, un array di interi, con tutti gli elementi inizializzati a 0 e un array di caratteri, con tutti gli elementi inizializzati con il carattere vuoto. Ovviamente, possono accettare anche i consueti lambda di accompagnamento:

val arr01 = IntArray(5) {x -> (x +2)}

Per lavorare con gli array abbiamo davveri metodi a disposizione, li trovate tutti nella pagina ufficiale. Di seguito mostro i casi che mi sembrano più utili nella pratica.

Abbiamo visto come l'operatore [] insieme a get ci permetta di estrarre un elemento ad un dato indice.

Sempre
[] e set(indice, valore) ci permettono di modificare l'elemento specificato l'indice.

var arr02 = IntArray(5) {x -> (x +2)}
arr02[1] = 100
arr02.set(3,1000)


come sempre, l'array deve essere definito tramite var e non val.

Per verificare se l'array contiene un certo elemento esiste contains(elemento) che restituisce true o false, quindi un valore bboleano.

println(arr02.contains(100))

Per attraversare un array, pratica molto comune, possiamo fare in vari modi. Per esempio, volendo stampare tutti gli elementi possiamo scivere, semplicemente:

val arr01 = IntArray(15) {x -> (x + 2)}
for (x in 0..arr01.size-1)
{
  print("${arr01[x]} ")
}

oppure si può ricorrere a indices,  proprietà che ritorna un range costituito dall'insieme degli indici dell'array:

val arr01 = IntArray(15) {x -> (x + 2)}
for (x in arr01.indices)
{
  print("${arr01[x]} ")
}

Per effettuare la copia di un array abbiamo l'utile istruzione copyOf che presenta due sintassi:

copyOf()
copyOf(size)


La differenza sta nel fatto, come si capisce, che la prima effettua una copia semplice, la seconda forma permette di specificare una diversa dimensione per l'array che viene creato a partite dal primo. L'esempio che segue chiarisce anche un altro aspetto, ovvero che, una volta creata la copia, modifiche effettuate sul primo array non influiscono sul secondo (vedere righe 11, 12 e 13), cioè gli array sono indipendenti l'uno dall'altro.

  Esempio 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun main(args: Array<String>)
{
  val arr01 = IntArray(5) {x -> (x + 2)}
  println(arr01[2])
  val arr02 = arr01.copyOf()
  println(arr02[2])
  val arr03 = arr01.copyOf(10)
  println(arr01.size)
  println(arr03.size)
  println(arr03[6])
  arr01 [1] = 123
  println(arr01[1])
  println(arr02[1])
}

Alla riga 5 viene creata una copia identica dell'array arr01 in arr02 mentre arr03 contiene gli stessi elememnti di arr01 ma in più vi aggiunge altri elementi inizializzati a 0. E' anche possibile specificare una size minore rispetto a quella dell'array di cui sarà effettuata la copia, in questo caso verranno copiati solo i primi elementi fiuno a riempire la dimensione dell'array di destinazione.
Ancora, è possibile copiare solo una parte di un array tramite copyOfRange(indice-di-partenza, indice-di-arrivo), per la quale dovete fare attenzione che copia dall'indice di partenza all'indice di arrivo - 1.

val arr02 = arr01.copyOfRange(1,3)

questa istruzione copia dall'indice 1 al 2.

Molto utile è fill(elemento) che riempie l'array con l'elemento indicato. Internamente è definita come segue:

fun <T> Array<T>.fill(
    element: T, 
    fromIndex: Int = 0, 
    toIndex: Int = size)

Anche in questo caso l'indice finale è quello indicato dal parametro toIndex - 1.

Trovare l'indice del primo elemento che cercate in un array è possibile con indexOf(elemento):

print(arr01.indexOf(8))

Se l'elemento non esiste vi verrà restituito un bel -1 e anche questo è, eventualmente, un test per verificare l'esistenza di un elemento in un array. Del tutto analogo è lastIndexOf.

isEmpty e isNotEmpty testano se l'array è vuoto oppure no. L'uso è banale.

max() e min() ci restituiscono il più grande ed il più piccolo elemento dell'array o null se questo è vuoto.

il metodo plus(elemento) crea un array aggiungendo l'elemento indicato.

val arr01 = IntArray(15) {x -> (x + 2)}
var arr02 = arr01.plus(50)


la stessa istruzione può essere usata per concatenare due array:

val arr01 = arrayOf(1,2,3,4)
val arr02 = arrayOf(5,6,7)
val arr03 = arr01.plus(arr02)


Il classico sort() permette di ordinare in forma crescente gli elementi di un array nell'array stesso..


var arr01 = arrayOf(3,5,9,8,6,0,9,3,4)
arr01.sort()
for (i in 0..arr01.size-1)
print("${arr01[i] } ")

Se volete invertire gli elementi invece dovrete ricorrere ad un'altra classica istruzione, reverse().

Insomma c'è veramente tanta roba, ripeto che nella pagina ufficiale troverete tantissimo materiale.