Массивы как тип данных

Массив можно представить как сгруппированные вместе данные одного типа. При этом заранее известно количество этих данных-элементов, а также у каждого элемента есть свое место в массиве. На рисунке ниже показан пример одного массива, элементами которого являются целые числа. Каждое число лежит в своей ячейке, а над ячейкой написан ее номер – индекс элемента.

Такая "упаковка" данных обеспечивает удобство их обработки, когда значений слишком много, чтобы присваивать каждое отдельной переменной. Проще присвоить одной переменной целую группу, а к элементам в случае необходимости обращаться по их индексу.

В языке программирования Kotlin тип данных "массив" обозначается словом Array. Объявление переменных этого типа ничем не отличается от объявления переменных ранее нами изученных, за исключением того, что дополнительно указывается тип элементов массива. Это делается в угловых скобках после слова Array.

Примеры объявления массивов разных типов:

fun main() {
    val a: Array<Int>; 
    val b: Array<String>;
    val c: Array<Double>;
}

Здесь массив a предназначен для хранения целых чисел, b – строк, c – вещественных чисел.

Другими словами, несмотря на то, что сам массив – Array – это один тип данных, на самом деле это тип с вариациями, так называемый дженерик – общий. Поэтому переменной, объявленной как массив целых чисел, нельзя присвоить, например, массив строк.

Самый простой способ инициировать значением переменную типа Array – это вызвать встроенную в Kotlin функцию arrayOf(), которой в скобках передать через запятую элементы массива. Функция сама посчитает их количество, которое потом мы можем узнать через свойство массива size.

fun main() {
    val a: Array<Double> = arrayOf(1.0, 1.3, -1.2)
    val s: Int = a.size
    var i = 0
 
    while (i < s) {
        println(a[i])
        i++
    }
}

В программе на экран выводятся значения элементов массива. К ним мы обращаемся по индексу, который указывается в квадратных скобках после имени массива. В данном случае в цикле переменная i, которой мы назначили роль индекса, принимает значения 0, 1 и 2. Когда i становится равна трем, цикл завершает свою работу, потому что выражение 3 < 3 возвращает ложь (i равна трем и s равна трем).

С помощью квадратных скобок можно не только извлекать значение из массива (на самом деле оно не извлекается, а остается там, мы просто его "берем и смотрим"), но и менять значение в ячейке, обращаясь к ней по индексу. Если после обращения к элементу массива стоит знак присвоения, значит элемент не извлекается, а перезаписывается.

fun main() {
    val a: Array<Double> = arrayOf(1.0, 1.3, -1.2)
 
    a[1] = 2.8
    a[0] = a[2] * 2
 
    println(a[0])
    println(a[1])
    println(a[2])
}

Обратите внимание, что массив объявлен как неизменяемый – через val. Однако это не мешает нам изменять значение его элементов. На самом деле переменная действительно остается неизменяемой. Ей нельзя присвоить другой массив. Но в самом массиве менять элементы можно.

Заполним массив случайными числами:

import kotlin.random.Random
 
fun main() {
    val a: Array<Int> = arrayOf(0, 0, 0, 0, 0)
    var i = 0
 
    while (i < a.size) {
        a[i] = Random.nextInt(10)
        print(a[i])
        print(" ")
        i++
    }
}

Если массив надо инициировать не пятью значениями, а, скажем, сотней, то записать такое количество нулей в вызове функции arrayOf() будет проблематично.

Есть другой способ создания массива – путем вызова класса Array. Как уже было сказано, типы данных это и есть классы данных. В Kotlin имя класса, упомянутое после знака присваивания, означает вызов конструктора этого класса. Конструктор создает объект этого типа, то есть экземпляр класса.

В конструктор класса Array мы должны передать количество элементов массива и так называемую лямбда-функцию, посредством которой будут вычислены значения элементов массива. В простейшем случае, если мы хотим инициировать все элементы одинаковым значением, достаточно передать это значение. Однако заключать его надо в фигурные скобки, так как по сути это сокращенная до нельзя лямбда-функция.

val a: Array<Int> = Array(5, {0})

В Kotlin такой лямбда-аргумент функции принято выносить за скобку:

val a: Array<Int> = Array(5) {0}

На скрине вместо цикла while используется цикл for, особенности работы которого мы рассмотрим в следующем уроке.

Практическая работа:

  1. Заполните массив строками, которые пользователь вводит с клавиатуры и затем выведите их на экран в обратном порядке.

  2. Заполните массив случайными целыми числами. Найдите элементы с максимальным и минимальным значением, используя функции-методы массива min() и max().

PDF-версия курса с ответами к практическим работам


Kotlin с нуля. Курс для начинающих




Все разделы сайта