Освой Kotlin играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Массивы

val vs var
Конструктор Array()
Класс Arrays
Перевернуть массив: reversedArray()
Перевернуть массив: reverse()
Сортировка элементов массива
Содержится ли элемент в массиве
Подсчитать сумму чисел в массиве
Найти среднее значение чисел в массиве
Найти наибольшее и наименьшее число в массиве
Найти общие элементы двух массивов

Рассмотрим работу с массивами в Kotlin, которые являются классами.

Массив можно создать двумя способами - через конструктор Array() или через методы arrayOf(), arrayOfNulls(), emptyArray().

arrayOf()

Создадим массив и получим значение третьего элемента.


val myArray = arrayOf(1, 2, 3, 4, 5)
println(myArray[2])

Узнать длину массива можно при помощи свойства size.


println(myArray.size) // 5

А что случится, если мы добавим в массив строки?


val myArray = arrayOf(1, 2, 3, 4, 5, "зайчик", "вышел", "погулять")
println(myArray[5])

Ничего страшного, у нас получился массив смешанного типа. Всё работает, ничего не ломается.

Если мы хотим строгого поведения и не хотим смешивать разные типы, то используем обобщения.


val myArray = arrayOf<Int>(1, 2, 3, 4, 5) // только числа Integer

Существует также синонимы метода, когда уже в имени содержится подсказка: intArrayOf(), harArrayOf(), booleanArrayOf(), longArrayOf(), shortArrayOf(), byteArrayOf().

Перепишем пример.


val myArray = intArrayOf(1, 2, 3, 4, 5)

Пройтись по элементам массива и узнать значение индекса можно с помощью метода withIndex():


val numbersArray = intArrayOf(1, 2, 3, 4, 5)
for ((index, value) in numbersArray.withIndex()) {
    println("Значение индекса $index равно $value")
}

У массива есть свойство indices и мы можем переписать пример по другому.


val numbersArray = intArrayOf(1, 2, 3, 4, 5)
for (index in numbersArray.indices) {
    println("Значение индекса $index равно ${numbersArray[index]}")
}

arrayOfNulls()

Для создания массива с заполненными значениями null можно использовать отдельную функцию arrayOfNulls().

Создадим массив с тремя элементами.


val array = arrayOfNulls(3) // [null, null, null]

Присвоим значения пустым элементам.


var arr2 = arrayOfNulls<String>(2)
arr2.set(0, "1")
arr2.set(1, "2")

// или
arr2[0] = "1"
arr2[1] = "2"

// получить значения
println(arr2[0]) // или arr2.get(0)
println(arr2[1])

emptyArray()

Создадим пустой массив и заполним его данными.


var arr = emptyArray<String>()
arr += "1"
arr += "2"
arr += "3"
arr += "4"
arr += "5"

val vs var

Нужно уяснить разницу между var и val при работе с массивами.


// Создали новый массив
var myArray = arrayOf(1, 2, 3)

// Это совершенно новый массив
myArray = arrayOf(4, 5)

Фактически мы уничтожили первый массив и создали вместо него второй массив.

Если мы попытаем написать такой же код с использованием val, то компилятор запретит такое действие.


// Создали новый массив
val myArray = arrayOf(1, 2, 3)

// Нельзя. Компилятор не пропустит
myArray = arrayOf(4, 5)

Но при этом вы можете менять значения элементов массива, созданного через val.


val myArray = arrayOf(1, 2)
myArray[0] = 3 // меняем первый элемент массива
myArray[1] = 4 // меняем второй элемент массива

Конструктор Array()

При использовании конструктора нужно указать размер массива в первом параметре и лямбда-выражение во втором.


val myArray = Array(5, { i -> i * 2 })
println(myArray[3])

Мы задали пять элементов и каждый элемент в цикле умножаем на 2. В итоге получим массив чисел 0, 2, 4, 6, 8.

Создадим массив строк от "A" до "Z"


val letters = Array<String>(26) { i -> ('A' + i).toString() }
println(letters.joinToString(""))

Лямбда-выражение принимает индекс элемента массива и возвращает значение, которое будет помещено в массив с этим индексом. Значение вычисляется путём сложения индекса с кодом символа и преобразованием результата в строку.

Можно опустить тип массива и написать Array(26), компилятор самостоятельно определит нужный тип.

Есть отдельные классы для каждого примитивного типа - IntArray, ByteArray, CharArray и т.д.


val zeros = IntArray(3) // первый способ
val zeros = intArrayOf(0, 0, 0) // второй способ при помощи фабричного метода
println(zeros.joinToString())

Можно использовать лямбда-выражение.


val intArray = IntArray(4){i -> i + i}
println(intArray.joinToString())

Класс Arrays

Для вывода значений массива используйте класс Arrays с методом toString(), который вернёт результат в удобном и читаемом виде.


println(Arrays.toString(arr))

Перебор элементов массива

Обычный перебор через for.


val arr = arrayOf(1, 2, 3, 4, 5)

for (i in arr) {
    println("Значение элемента равно $i")
}

Можно одной строкой через forEach.


arr.forEach { i -> println("Значение элемента равно $i") }

Если нужна информация не только о значении элемента, но и его индексе, то используем forEachIndexed.


arr.forEachIndexed { index, element ->
    println("$index : $element")
}

// Результат
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5

Перевернуть массив: reversedArray()

Для операции создадим дополнительную переменную для нового массива с перевёрнутыми значениями. Оригинал останется без изменений.


val numbers: IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
var reversedArray = numbers.reversedArray()

println(Arrays.toString(reversedArray))

Перевернуть массив: reverse()

Если оригинал массива нам точно не понадобится, то мы можем перевернуть его без создания нового массива.


val numbers: IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
numbers.reverse()

println(Arrays.toString(numbers))

Сортировка элементов массива

В Kotlin очень просто сортировать элементы.

Вызываем метод sort(). Мы меняем существующий массив, а не создаём новый.


val numbers: IntArray = intArrayOf(7, 5, 8, 4, 9, 6, 1, 3, 2)
numbers.sort()

println(Arrays.toString(numbers))

Сортировать можно не весь массив, а только определённый диапазон. Указываем начало и размер диапазона. Допустим, нам нужно отсортировать только первые три элемента из предыдущего примера.


numbers.sort(0, 3)

// 5, 7, 8, 4, 9, 6, 1, 3, 2

Сортировка в обратном порядке от наибольшего значения к наименьшему.


numbers.sortDescending()

Если нужно сохранить исходный массив, то вызываем другие функции, которые создадут новый массив.


val numbers: IntArray = intArrayOf(7, 5, 8, 4, 9, 6, 1, 3, 2)
val sortedNumbers: IntArray = numbers.sortedArray() // новый сортированный массив
val descendingSortedNumber: IntArray = numbers.sortedArrayDescending() // новый сортированный массив в обратном порядке

println(Arrays.toString(numbers) + ":" + Arrays.toString(sortedNumbers))
// [7, 5, 8, 4, 9, 6, 1, 3, 2]:[1, 2, 3, 4, 5, 6, 7, 8, 9]:[9, 8, 7, 6, 5, 4, 3, 2, 1]

Для сортировки объектов указываем компаратор и условие сравнения. Например, мы хотим сравнить котов по их возрастам.


val cats = arrayOf(Cat("Барсик", 8), Cat("Мурзик", 4), Cat("Васька", 9))
// массив до сортировки
cats.forEach { println(it) }

// сортируем по возрасту
cats.sortWith(Comparator { c1: Cat, c2: Cat -> c1.age - c2.age })
cats.forEach { println(it) }


data class Cat(val name: String, val age: Int)

Вместо компаратора можно использовать функцию sortBy() с указанием условия. Сравним теперь котов не по возрасту, а по их именам.


val cats = arrayOf(Cat("Барсик", 8), Cat("Мурзик", 4), Cat("Васька", 9))
cats.forEach { println(it) }
cats.sortBy { cat -> cat.name }
cats.forEach { println(it) }


data class Cat(val name: String, val age: Int)

Содержится ли элемент в массиве

Если содержится, то возвращает true.


val array = arrayOf(1, 2, 3, 4, 5)
val isContains = array.contains(9)
println(isContains) // false

Найти среднее значение чисел в массиве

Используем функцию average(). Возвращается Double.


val array = arrayOf(1, 3, 5)
println(array.average()) // 3.0

Подсчитать сумму чисел в массиве


val array = arrayOf(1, 2, 3, 4, 5)
println(array.sum()) // 15

Найти наибольшее и наименьшее число в массиве

В цикле сравниваем каждое число с эталоном, которые вначале принимает значение первого элемента. Если следующее число массива больше эталона, то берём его значение. В итоге после перебора получим наибольшее число в массиве.


val numbers: IntArray = intArrayOf(4, 9, 3, 2, 6)
var largestElement = numbers[0]

for (number in numbers){
    if(largestElement < number)
        largestElement = number
}

println("Наибольшее число в массиве: $largestElement")

Но можно не писать свой код, а вызвать готовые функции min() и max().


println(numbers.min())
println(numbers.max())

Найти общие элементы двух массивов

Есть два массива с числами. Нужно сравнить их и найти у них общие числа. Поможет нам функция intersect()


val firstArray = arrayOf(1, 2, 3, 4, 5)
val secondArray = arrayOf(3, 5, 6, 7, 8)

val intersectedArray = firstArray.intersect(secondArray.toList()).toIntArray()
println(Arrays.toString(intersectedArray))

//[3, 5]
Реклама