Kotlin Desde Cero: Rangos y Colecciones
Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)
Kotlin es una lenguaje moderno de programación que compila a código byte Java. Es gratuito y de código abierto, y promete hacer el codificar para Android incluso más divertido.
En el artículo anterior en esta serie, aprendiste sobre nulidad, ciclos, y condiciones en Kotlin. En este tutorial, continuaremos aprendiendo el lenguaje viendo la API de rangos y colecciones en Kotlin.
1. Rangos
Un Rango en Kotlin es un tipo único que define un valor de inicio y un valor final. En otras palabras, es un intervalo entre un valor de inicio y uno final. Los Rangos en Kotlin son cerrados, significando que el valor inicial y el valor final están incluidos en el rango.
Ahora veremos diferentes maneras de crear rangos en Kotlin.
El Operador ..
1 |
val oneToFive = 1..5 |
En el código de arriba, hemos creado un rango cerrado. Esta variable oneToFive incluirá los siguientes valores: 1, 2, 3, 4, 5. Podemos ciclar sobre este usando el constructor de ciclo for.
1 |
for (n in oneToFive) { |
2 |
print(n) |
3 |
}
|
El código de arriba puede ser acortado a:
1 |
for (n in 1..5) { |
2 |
print(n) |
3 |
}
|
También podemos crear un rango de caracteres:
1 |
val aToZ = "a".."z" |
La variable aToZ tendrá todas las letras en el alfabeto Inglés.
La Función rangeTo()
El operador .. puede ser reemplazado con la función de extensión rangeTo() para crear un rango. Por ejemplo, también podemos hacer esto 1.rangeTo(5) y aún tener los mismos resultados que usar el operador .. como discutimos anteriormente.
1 |
val oneToFive: IntRange = 1.rangeTo(5) |
La Función downTo()
Esta es otra función de extensión que creará un rango comenzando desde un número dado hacia otro.
1 |
val fiveToOne = 5.downTo(1) |
Podemos modificar el rango usando la función step(). Esto modificará el delta entre cada elemento en el rango.
1 |
val oneToTenStep = 1..10 step 2 // 1, 3, 5, 7, 9 |
El código de arriba contendrá números impares entre 1 y 10.
El Operador in
El operador in es usado para cerciorarse si un valor está presente en un rango dado.
1 |
if (5 in 1..10) { |
2 |
print("Yes 5 is in the range") // prints "Yes 5 is in the range" |
3 |
}
|
En el código de arriba, revisamos para ver si 5 está en el rango 1..10 usando el operador in. También podemos hacer lo contrario usando !n para revisar si 5 no está en el rango.
2. Colecciones
Las colecciones son usadas para almacenar grupos de objetos relacionados en memoria. En una colección, podemos recuperar, almacenar u organizar los objetos. Kotlin proporciona su API de colecciones como una librería estándar construida encima de la API de Colecciones Java. (Discutiremos interfaces en Kotlin en un artículo futuro.)
Deberías notar que estas interfaces están enlazadas a sus implementaciones en tiempo de compilación. No puedes ver el código fuente de implementación en Kotlin, porque sus colecciones son de hecho implementadas por las Colecciones Java estándar tales como ArrayList, Maps, HashMap, Sets, HashSet, List y así por el estilo. Para entender realmente la API de colecciones en Kotlin, necesitarás estar familiarizado con las clases básicas e interfaces en Java.
En esta sección, aprenderemos sobre las colecciones List, Set y Map en Kotlin. (Si quieres un recordatorio sobre arreglos en Kotlin, por favor visita el primer tutorial en esta serie.)
Las colecciones de Kotlin nos dan la habilidad para lograr mucho con solo un poco de código---¡a diferencia de Java, que parece necesitar mucho código para lograr un poco! Kotlin tiene dos variantes de colecciones: mutable e inmutable. Una colección mutable nos proporciona la habilidad de modificar una colección ya sea agregando, removiendo o reemplazando un elemento. Las colecciones inmutables no pueden ser modificadas y no tienen estos métodos de ayuda.
Nota que la adición, remoción o reemplazo de un elemento en una colección inmutable es posible vía funciones operador (llegaremos a eso pronto), pero estas terminarán creando una nueva colección.
La Interfaz Iterable
La interfaz Iterable Kotlin está encima de la clase de jerarquía de colecciones. Esta interfaz habilita a las colecciones para ser representadas como una secuencia de elementos (que pueden ser iteradas, naturalmente),
1 |
public interface Iterable<out T> { |
2 |
public abstract operator fun iterator(): Iterator<T> |
3 |
}
|
La Interfaz Collection
La interfaz Collection de Kotlin extiende a la interfaz Iterable. La interfaz Collection es inmutable. Las interfaces Set y List (más sobre estas pronto) en Kotlin extienden a esta interfaz.
Algunas de las funciones y propiedades disponibles en la interfaz Collection son:
-
size: esta propiedad devuelve el tamaño de la colección. -
isEmpty(): devuelve verdadero si la colección está vacía o falso en caso contrario. -
contains(element: E): devuelve verdadero si el elemento especificado en el argumento está presente en la colección. - containsAll(element: Collection<E>): devuelve verdadero si el elemento en la colección pasado como argumento está presente en la colección.
1 |
public interface Collection<out E> : Iterable<E> { |
2 |
public val size: Int |
3 |
public fun isEmpty(): Boolean |
4 |
public operator fun contains(element: @UnsafeVariance E): Boolean |
5 |
override fun iterator(): Iterator<E> |
6 |
public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean |
7 |
}
|
La Interfaz MutableIterable
Esta interfaz en Kotlin nos da un iterador mutable especializado de la interfaz padre Iterable.
1 |
public interface MutableIterable<out T> : Iterable<T> { |
2 |
override fun iterator(): MutableIterator<T> |
3 |
}
|
La Interfaz MutableCollection
La interfaz MutableCollection en Kotlin es una interfaz especializada que habilita a las colecciones para ser mutables. En otras palabras, agregar o remover operaciones puede ser realizado en una colección dada. Esta interfaz extiende a la interfaz Collection y la interfaz MutableIterable que ya discutimos arriba. Las interfaces MutableSet y MutableList (llegaremos a ellas pronto) en Kotlin extiende a esta interfaz. Las funciones disponibles en esta interfaz---además de las que están disponibles en sus padres---son:
-
add(element: E):agrega el elemento pasado como un argumento a la colección y devuelve verdadero si es exitoso o falso si la colección no soporta duplicados y los elementos ya están presentes.
-
remove(element: E): remueve el elemento pasado como un argumento de la colección. Devuelve verdadero si es exitoso o falso si no estaba presente en la colección. - addAll(elements: Collection<E>): agrega todos los elementos en la colección pasados como argumentos a la colección. Devuelve verdadero si es exitoso o falso si nada se agregó.
- removeAll(elements: Collection<E>): remueve todos los elementos presentes en la colección pasados como argumentos. Devuelve verdadero si es exitoso o falso si nada es removido.
- retainAll(elements: Collection<E>): retiene solo los elementos presentes en las colecciones pasadas como argumentos. Devuelve verdadero si es exitoso o falso si nada fue retenido.
-
clear(): remueve todos los elementos de esta colección.
1 |
public interface MutableCollection<E> : Collection<E>, MutableIterable<E> { |
2 |
override fun iterator(): MutableIterator<E> |
3 |
public fun add(element: E): Boolean |
4 |
public fun remove(element: E): Boolean |
5 |
public fun addAll(elements: Collection<E>): Boolean |
6 |
public fun removeAll(elements: Collection<E>): Boolean |
7 |
public fun retainAll(elements: Collection<E>): Boolean |
8 |
public fun clear(): Unit |
9 |
}
|
Ahora has aprendido sobre las principales interfaces en la clase de jerarquía de colección en Kotlin, echemos ahora un vistazo a cómo maneja Kotlin colecciones tales como Listas, Conjuntos y Mapas en la parte restante de este tutorial.
Listas
Una lista es una colección ordenada de elementos. Esta es una colección popular que es ampliamente usada. Veamos diferentes maneras de crear una lista en Kotlin.
Usando la Función listOf()
En Kotlin, podemos crear una lista inmutable (solo lectura) usando la función de ayuda listOf() desde la librería estándar Kotlin. Esta función devuelve un tipo de interfaz Kotlin List.
1 |
var numbers: List<Int> = listOf(1, 2, 3, 4, 5) |
2 |
var names: List<String> = listOf("Chike", "Nnamdi", "Mgbemena") |
3 |
for (name in names) { |
4 |
println(name) |
5 |
}
|
Ejecutar el código de arriba imprimirá:
1 |
Chike |
2 |
Nnamdi |
3 |
Mgbemena |
Además, podemos pasar valores en diferentes tipos al listOf() como argumentos y el resultado aún funcionará---será una lista de tipo mixto.
1 |
var listMixedTypes = listOf("Chike", 1, 2.445, 's') // will still compile |
Usando la Función emptyList()
Esta función solo crea una lista inmutable y devuelve una interfaz tipo Kotlin List.
1 |
val emptyList: List<String> = emptyList<String>() |
Usando la Función listOfNotNull()
Esta función crea una nueva lista inmutable conteniendo solo elementos que no son nulos. Nota que esta función devuelve una interfaz tipo Kotlin List también.
1 |
val nonNullsList: List<String> = listOfNotNull(2, 45, 2, null, 5, null) |
La interfaz List de la librería estándar Kotlin extiende solo la interfaz Collection. En otra palabras, su único padre es la interfaz Collection. Esta anula todas las funciones en la interfaz padre para abastecer sus necesidades especiales y también define sus propias funciones, tales como:
-
get(index: Int): un operador de función que devuelve el elemento en el índice especificado. -
indexOf(element: E): devuelve el índice de la primera ocurrencia del elemento pasado como un argumento en la lista, o -1 si ninguno es encontrado.
-
lastIndexOf(element: E): devuelve el índice de la última ocurrencia del elemento pasado como un argumento en la lista, o -1 si ninguno es encontrado. -
listIterator(): devuelve un iterador de lista sobre los elementos en la lista. -
subList(fromIndex: Int, toIndex: Int): devuelve una lista que contiene la porción de la lista entre los índices especificados de inicio y fin.
1 |
println(names.size) // 3 |
2 |
println(names.get(0)) // "Chike" |
3 |
println(names.indexOf("Mgbemena")) // 2 |
4 |
println(names.contains("Nnamdi")) // 'true' |
Usando la Función arrayListOf()
Esto crea una lista mutable y devuelve un tipo Java ArrayList.
1 |
val stringList: ArrayList<String> = arrayListOf<String>("Hello", "You", "There") |
Usando la Función mutableListOf()
Para agregar, remover o reemplazar valores en una lista, necesitamos hacer a la lista mutable. Podemos convertir una lista inmutable a una mutable llamando a la función toMutableList() en la lista. Sin embargo, nota que este método creará una nueva lista.
1 |
var mutableNames1 = names.toMutableList() |
2 |
mutableNames1.add("Ruth") // now mutable and added "Ruth" to list |
Para crear una lista mutable de un cierto tipo desde cero, ej. String, usamos mutableListOf<String>(), mientras que para tipos mixtos podemos solo usar la función mutableListOf() en su lugar.
1 |
// a mutable list of a certain type e.g. String
|
2 |
val mutableListNames: MutableList<String> = mutableListOf<String>("Josh", "Kene", "Sanya") |
3 |
mutableListNames.add("Mary") |
4 |
mutableListNames.removeAt(1) |
5 |
mutableListNames[0] = "Oluchi" // replaces the element in index 0 with "Oluchi" |
6 |
|
7 |
// a mutable list of mixed types
|
8 |
val mutableListMixed = mutableListOf("BMW", "Toyota", 1, 6.76, 'v') |
Cualquiera de estas funciones devolverá una interfaz tipo Kotlin MutableList. Esta interfaz extiende las interfaces MutableCollection y List discutidas anteriormente en esta sección. La interfaz MutableList agrega métodos para la recuperación o sustitución de un elemento basado en su posición:
-
set(index: Int, element: E): sustituye a un elemento en la lista con otro elemento. Esto devuelve el elemento previamente en la posición especificada.
-
add(index: Int, element: E): inserta un elemento en el índice especificado. -
removeAt(index: Int): se deshace del elemento en un índice particular.
1 |
val mutableListFood: MutableList<String> = mutableListOf<String>("Rice & stew", "Jollof rice", "Eba & Egusi", "Fried rice") |
2 |
mutableListFood.remove("Fried rice") |
3 |
mutableListFood.removeAt(0) |
4 |
mutableListFood.set(0, "Beans") |
5 |
mutableListFood.add(1, "Bread & tea") |
6 |
|
7 |
for (foodName in mutableListFood) { |
8 |
println(foodName) |
9 |
}
|
Ejecutando el código de arriba, producimos el siguiente resultado:
1 |
Beans |
2 |
Bread & tea |
3 |
Eba & Egusi |
Nota que todas estas funciones crear un ArrayList Java tras bambalinas.
Conjuntos
Un conjunto es una colección sin orden de elementos únicos. En otras palabras, ¡no puede tener ningún duplicado! Veamos algunas de las diferentes maneras de crear un conjunto en Kotlin. Cada una de estas crea una estructura diferente de datos, de las cuáles cada una está optimizada para un cierto tipo de tarea.
Usando la Función setOf()
Para crear un conjunto inmutable (solo lectura) en Kotlin, podemos usar la función setOf(), la cuál devuelve una interfaz tipo Kotlin Set.
1 |
// creates a immutable set of mixed types
|
2 |
val mixedTypesSet = setOf(2, 4.454, "how", "far", 'c') // will compile |
3 |
|
4 |
var intSet: Set<Int> = setOf(1, 3, 4) // only integers types allowed |
Nota que la interfaz Kotlin Set extiende solo a la interfaz Kotlin Collection y anula todas las propiedades disponibles en su padre.
Usando la Función hashSetOf()
Usar la función hashSetOf() crea una colección Java HashSet que almacena elementos en una tabla hash. Debido a que esta función devuelve un tipo Java HashSet, podemos agregar, remover, o despejar elementos en el conjunto. En otras palabras, es mutable.
1 |
val intsHashSet: java.util.HashSet<Int> = hashSetOf(1, 2, 6, 3) |
2 |
intsHashSet.add(5) |
3 |
intsHashSet.remove(1) |
Usando la Función sortedSetOf()
Usar la función sortedSetOf() crea una colección Java TreeSet tras bambalinas, la cuál ordena elementos basado en su ordenamiento natural o por un comparador. Este conjunto también es mutable.
1 |
val intsSortedSet: java.util.TreeSet<Int> = sortedSetOf(4, 1, 7, 2) |
2 |
intsSortedSet.add(6) |
3 |
intsSortedSet.remove(1) |
4 |
intsSortedSet.clear() |
Usando la Función linkedSetOf()
Esta función devuelve un tipo Java LinkedHashSet. Este conjunto mutable mantiene una lista enlazada de entradas en el conjunto, en el orden en el cuál fueron insertadas.
1 |
val intsLinkedHashSet: java.util.LinkedHashSet<Int> = linkedSetOf(5, 2, 7, 2, 5) // 5, 2, 7 |
2 |
intsLinkedHashSet.add(4) |
3 |
intsLinkedHashSet.remove(2) |
4 |
intsLinkedHashSet.clear() |
Usando la Función mutableSetOf()
Podemos usar mutableSetOf() para crear un conjunto mutable. Esta función devuelve una interfaz tipo Kotlin MutableSet. Tras bambalinas, esta función simplemente crea un LinkedHashSet Java.
1 |
// creates a mutable set of int types only
|
2 |
val intsMutableSet: MutableSet<Int> = mutableSetOf(3, 5, 6, 2, 0) |
3 |
intsMutableSet.add(8) |
4 |
intsMutableSet.remove(3) |
La interfaz MutableSet extiende a las interfaces MutableCollection y Set.
Mapas
Los mapas asocian claves con valores. Las claves deben ser únicas, pero los valores asociados no. De eso modo, cada valor puede ser usado para identificar de manera única el valor asociado, ya que el mapa asegura que no puedes duplicar claves en la colección. Detrás de escenas, Kotlin usa la colección Java Map para implementar su tipo de colección de mapa.
Usando la Función mapOf()
Para crear una colección Map inmutable o de solo lectura en Kotlin, usamos la función mapOf(). Creamos un mapa con esta función dándole una lista de pares---el primer valor es la clave, y el segundo es el valor. Llamar a esta función devuelve una interfaz tipo Kotlin Map.
1 |
val callingCodesMap: Map<Int, String> = mapOf(234 to "Nigeria", 1 to "USA", 233 to "Ghana") |
2 |
for ((key, value) in callingCodesMap) { |
3 |
println("$key is the calling code for $value") |
4 |
}
|
5 |
print(callingCodesMap[234]) // Nigeria |
Ejecutar el código de arriba producirá el resultado:
1 |
234 is the calling code for Nigeria |
2 |
1 is the calling code for USA |
3 |
233 is the calling code for Ghana |
A diferencia de las interfaces List y Set en Kotlin que extienden la interfaz Collection, la interfaz Map no extiende nada. Algunas de las propiedades y funciones disponibles en esta interfaz son:
-
tamaño: esta propiedad devuelve el tamaño de colección mapa. -
isEmpty(): devuelve verdadero si el mapa está vacío o falso de otro modo. -
containsKey(key: K): devuelve verdadero si el mapa contiene la clave en el argumento. -
containsValue(value: V): devuelve verdadero si el mapa mapea una o más claves al valor pasado como un argumento. -
get(key: K): devuelve el valor empatando la llave dada o 'null' si no se encuentra ninguno. -
keys: esta propiedad devuelve unSetinmutable de todas las claves en el mapa. -
values: devuelve unaCollectioninmutable de todos los valores en el mapa.
Usando la Función mutableMapOf()
La función mutableMapOf() crea un mapa mutable por nosotros de manera que podamos agregar y remover elementos en el mapa. Esto devuelve una interfaz tipo Kotlin MutableMap.
1 |
val currenciesMutableMap: MutableMap<String, String> = mutableMapOf("Naira" to "Nigeria", "Dollars" to "USA", "Pounds" to "UK") |
2 |
println("Countries are ${currenciesMutableMap.values}") // Countries are [Nigeria, USA, UK] |
3 |
println("Currencies are ${currenciesMutableMap.keys}") // Currencies are [Naira, Dollars, Pounds] |
4 |
currenciesMutableMap.put("Cedi", "Ghana") |
5 |
currenciesMutableMap.remove("Dollars") |
La interfaz MutableMap no extiende la interfaz MutableCollection; su único padre es la interfaz Map. Este anula las propiedades keys, entries y values desde la interfaz padre para poder redefinirlas. Aquí hay algunas funciones extra disponibles en la interfaz MutableMap:
-
put(key: K, value: V): inserta el par de valores de clave en el mapa. Esto devolverá el valor previo enlazado con la clave o null si la clave no fue usada anteriormente. -
remove(key: K): remueve la clave y su valor enlazado desde el mapa. -
putAll (from: Map<out K, V>): actualiza el mapa con todos los datos desde el mapa dado. Nuevas claves serán agregadas, y claves existentes serán actualizadas con nuevos valores. -
clear(): remueve todos los elementos del mapa.
Podemos obtener el valor de una clave usando la función get(). También podemos usar notación de llave cuadrada como un atajo para get().
1 |
print(currenciesMutableMap.get("Nigeria")) // will print Naira |
2 |
print(currenciesMutableMap["Nigeria"]) // will print Naira |
Usando la Función hashMapOf()
Usar esta función devuelve un tipo Java HashMap que es mutable. La clase HashMap usa una tabla hash para implementar la interfaz Java Map.
1 |
val personsHashMap: java.util.HashMap<Int, String> = hashMapOf(1 to "Chike", 2 to "John", 3 to "Emeka") |
2 |
personsHashMap.put(4, "Chuka") |
3 |
personsHashMap.remove(2) |
4 |
print(personsHashMap[1]) // will print Chike |
Usando la Función linkedHashMap()
Esta función devuelve un tipo Java LinkedHashMap que es mutable. La clase LinkedHashMap extiende a Java HashMap y mantiene una lista enlazada de entradas en el mapa para en el orden en el cuál fueron insertadas.
1 |
val postalCodesHashMap: java.util.LinkedHashMap<String, String> = |
2 |
linkedMapOf("NG" to "Nigeria","AU" to "Australia","CA" to "Canada") |
3 |
postalCodesHashMap.put("NA", "Namibia") |
4 |
postalCodesHashMap.remove("AU") |
5 |
postalCodesHashMap.get("CA") // Canada |
Usando la Función sortedMapOf()
Esta función devuelve un tipo Java SortedMap el cuál es mutable. La clase Java SortedMap ve que todas las entradas en el mapa sean mantenidas en un orden de clave ascendente.
1 |
val personsSortedMap: java.util.SortedMap<Int, String> = sortedMapOf(2 to "Chike", 1 to "John", 3 to "Emeka") |
2 |
personsSortedMap.put(7, "Adam") |
3 |
personsSortedMap.remove(3) |
Recuerda, la implementación de estas interfaces de colección en Kotlin suceden en tiempo de compilación.
Funciones de Colecciones de Operación
Kotlin nos proporciona muchas funciones operador llamadas funciones de extensión que pueden ser invocadas sobre colecciones. Echemos un vistazo a algunas de las más útiles.
La Función last()
Esta función operador devuelve el último elemento en una colección tal como una lista o conjunto. También podemos proveer un predicado para buscar dentro de un subconjunto de elementos.
1 |
val stringList: List<String> = listOf("in", "the", "club") |
2 |
print(stringList.last()) // will print "club" |
3 |
|
4 |
// given a predicate
|
5 |
print(stringList.last{ it.length == 3}) // will print "the" |
6 |
|
7 |
val intSet: Set<Int> = setOf(3, 5, 6, 6, 6, 3) |
8 |
print(intSet.last()) // will print 6 |
La Función first()
Esta función operador devuelve el primer elemento cuando se invoca sobre una colección tal como una lista o conjunto. Si un predicado es dado, entonces usa el predicado para restringir la operación a un subconjunto de elementos.
1 |
print(stringList.first()) // will print "in" |
2 |
print(intSet.first()) // will print 3 |
La Función max()
Invocar esta función operador sobre una colección tal como una lista o conjunto devuelve el elemento más grande, o nulo si no se encuentra un elemento más grande.
1 |
val intList: List<Int> = listOf(1, 3, 4) |
2 |
print(intList.max()) // will print 4 |
3 |
print(intSet.max()) // will print 6 |
La Función drop()
Llamar a esta función operador devuelve una nueva lista o conjunto conteniendo todos los elementos excepto los primeros n elementos.
1 |
print(stringList.drop(2)) // will print "club" |
La Función plus()
Esta función operador devuelve una colección conteniendo todos los elementos del original y después el elemento dado si no está ya en la colección. Esto terminará creando una nueva lista en vez de modificar la lista.
1 |
print(intList.plus(6)) // will print [1, 3, 4, 6] |
La Función minus()
El opuesto de la función plus() es la función minus(). Esta devuelve una colección conteniendo todos los elementos del conjunto original excepto el elemento dado. Esto termina creando una nueva lista en vez de alterar la lista.
1 |
print(intList.minus(3)) // will print [1, 4] |
La Función average()
Llamar esta función operador devolverá un número promedio de elementos en la colección.
1 |
print(intList.average()) // will print 2.6666666666666665 |
La mayoría de estas funciones de extensión están disponibles en la librería estándar de colecciones Kotlin. Se te recomienda revisar la documentación para aprender sobre las otras.
Conclusión
En este tutorial, aprendiste sobre la API de rango y colecciones en el lenguaje de programación Kotlin. En el siguiente tutorial en la serie Kotlin Desde Cero, se te presentarán funciones en Kotlin. ¡Te veo pronto!
Para aprender más sobre el lenguaje Kotlin, recomiendo visitar la documentación Kotlin. ¡O revisa algunos de nuestros artículos de desarrollo de apps Android aquí en Envato Tuts+!


SDK de AndroidIntroducción a Componentes de Arquitectura AndroidTin Megali

Aprendizaje AutomáticoCrea Chatbots en Android Con IBM WatsonAshraff Hathibelagal

SDK de AndroidJava vs. Kotlin: ¿Deberías Estar Usando Kotlin para Desarrollo Android?Jessica Thornsby

SDK de AndroidConsejo Rápido: Escribe Código Más Limpio Con Conversiones Kotlin SAMAshraff Hathibelagal

SDK de AndroidAndroid O: Verificación de Número de Teléfono Con Tokens SMSChike Mgbemena



