Создание массивов разных типов
Мы уже виртуозно умеем управляться с базовыми типами, такими как Int, String и так далее. Обычно мы создаем ряд переменных и работаем с ними. Представим, что мы делаем приложение с рецептами. И для яичницы есть 5 ингредиентов. Перечислим их.
val ingredient1 = "яйцо"
val ingredient2 = "помидор"
val ingredient3 = "зелень"
val ingredient4 = "соль"
val ingredient5 = "перец"
Мы создаем 5 отдельных переменных строкового типа. Но в условиях программы, когда нужно каким-либо образом обрабатывать их вместе, искать по ним или выводить на экран списком – делать это с отдельными переменными затруднительно.
Поэтому можно объединить эти строки в единый набор – массив. Массив – это набор данных одного типа. Важно также запомнить, что массив имеет фиксированную длину, которая устанавливается при его инициализации и в последствии не может быть изменена.
Принципы создания массивов
Функция arrayOf()
Массив создается по принципу обычной переменной. Создадим его с помощью ключевого слова val и назовем “массив ингредиентов”. Инициализация массива происходит с помощью функции arrayOf(). В параметры которой (в круглые скобки) заносим значения единого типа через запятую. В нашем стучае это строки. На всякий случай напомню, все что бы мы не написали в двойных кавычках будет являться строковым типом String. И число и какой-нибудь один символ.
val arrayOfIngredients = arrayOf("яйцо", "помидор", "зелень", "соль", "перец")
В итоге мы создали и сразу проинициализировали массив, соблюдая все правила. Все значения одного типа, их количество явно известно. Если навести на переменную курсор, подсветится ее тип – массив строк. Проставим тип переменной явно для наглядности:
val arrayOfIngredients: Array<String> = arrayOf("яйцо", "помидор", "зелень", "соль", "перец")
Точно также можно объявить массив целых чисел Int или символов Char:
val intArray: Array<Int> = arrayOf(4, 4, 2)
val charArray: Array<Char> = arrayOf('4', '4', '2')
Но такие массивы можно объявить еще с помощью типов: IntArray или CharArray. Создаются они с похожей функцией intArrayOf() или charArrayOf():
val intArray1: IntArray = intArrayOf(4, 4, 2)
val charArray1: CharArray = charArrayOf('4', '4', '2')
Нюансы инициализации
Разница в нюансах подкапотной работы создания массивов, отсылая нас к корням Java в виде примитивных массивов. Наглядная разница заключается в том, что intArrayOf() можно без явного указания типа оставить не проинициализированным, то есть пустым. В то время как arrayOf() вызовет ошибку. Напомню, явное проставление типов мы используем только для наглядности. По умолчанию тип переменной определяется автоматически, в зависимости от ее инициализации.
val intArray2 = arrayOf()
val intArray3 = intArrayOf()
Объявления массивов через val и var
Раз уж мы немного провалились в нюансы, стоит отметить еще важную деталь. Про разницу объявления массивов через val и var. Мы по-прежнему можем создавать их с помощью обоих ключевых слов, но разницу лучше прочувствовать на примере ниже.
Итак, у нас есть пустой intArray3. Заполним его каким-нибудь цифрами:
val intArray3 = intArrayOf(1, 2, 3, 4, 5)
Функция intArrayOf создаст новый массив с фиксированной длиной 5, и значениями, которые мы прописали в круглых скобках. Мы можем по умолчанию изменять его значения внутри на другие, об этом будет ниже. Но мы не можем пересоздать массив intArray3 в той же переменной с помощью функции intArrayOf. То есть при попытке перезаписать переменную с новой инициализацией будет ошибка. Даже, если значения внутри будут такими же, они уже будут иметь другие адреса в памяти, так что между ними не будет ничего общего. Ошибка возникает как раз, потому что изначально переменная создавалась с помощью val, что, как мы помним, является неизменяемой переменной. Как только изменим ключевое слово на var, ошибка уйдет, и функция intArrayOf пересоздаст массив и поместит его в переменную intArray3. Предыдущий массив будет уничтожен безвозвратно. Повторюсь, работать с данными внутри массива (читать, обнулять, сортировать и т.д.) можно в обоих случаях val и var, так мы не пересоздаем массив, а изменяем данные ячеек в памяти уже в созданном.
var intArray3 = intArrayOf(1, 2, 3)
intArray3 = intArrayOf(1, 2, 3, 4, 5)
Размер массива
Далее. Часто бывают ситуации, например, при создании условий и циклов, когда нужно получить размер массива. Сделать это можно с помощью обращения к свойству size у выбранного массива. Свойства или проперти – можно расценивать как поля класса. Мы обращаемся к полю класса Array – именно с этим типом мы создавали наш массив строк. И при создании и инициализации переменной в это свойство сохранилась информация о длине массива. Классы и их свойства мы будем изучать и рассматривать много раз далее по урокам. Сейчас выведем в консоль размер массива с ингредиентами:
println("Размер массива с ингредиентами: ${arrayOfIngredients.size}")
Вывод в консоль
Размер массива с ингредиентами: 5
Функция indexOf() в Kotlin
Окей. Мы создали разные массивы, и пора разобраться, как можно их читать, распечатывать и изменять. Посмотрим внимательнее на массив с ингредиентами. В нем 5 элементов. Представим их как 5 коробочек, которые лежат в ряд в определенном порядке. У каждой коробочки есть порядковый номер: первая, вторая и так далее. Будем называть это индексом. И эти индексы уже известны компилятору. Мы можем получить индекс какого-нибудь элемента с помощью функции indexOf(). Для этого у переменной массива вызовем метод через точку, а в его параметрах (в скобках) укажем сам элемент, например “помидор”. Выведем индекс в консоль.
println(arrayOfIngredients.indexOf("помидор"))
Мы получили число 1. Хотя этот элемент находится вторым по счету. Все верно – есть нюанс, который нужно принять и запомнить. Индекс во многих языках программирования начинается с нуля. Поэтому для нашего массива индексы будут такими: 0, 1, 2, 3, 4. Итого 5 элементов.
Отлично. Теперь, зная индексы, по ним можно обращаться к этим коробочкам или ячейкам, чтобы достать значение. Для этого в println() напишем массив и в квадратных скобках укажем нужный индекс. Например, 1 и 2. В квадратных скобках можно указать только один индекс.
println(arrayOfIngredients[1])
println(arrayOfIngredients[2])
Важно следить за тем, чтобы не обращаться по индексу за пределами массива. Например, если попытаться выбрать несуществующий элемент под индексом 5 или более – возникнет ошибка ArrayIndexOutOfBoundsException, что будет означать, что был осуществлен доступ к массиву с недопустимым индексом.
Итого мы достали два значения: “помидор” и “зелень”. Обращаясь по индексу можно не только доставать значения, но и изменять их. Например, изменим элемент “перец” на элемент “паприка”. Работаем как с присвоением значений в обычных переменных. Сначала пишем массив с указанием индекса куда класть новое значение. У элемента “перец” индекс 4. И справа от знака равно новое значение для записи в четвертый индекс. Выведем в консоль новое значение.
Код
Вывод в консоль
arrayOfIngredients[4] = "паприка"
println(arrayOfIngredients[4])
паприка
Функции set() и get()
Есть еще альтернативные способы чтения и записи данных в массив по индексу, с помощью функций set() и get(). В настоящее время среда разработки рекомендует заменить их на более интуитивно понятные с указанием индекса в квадратных скобках. Работа с перечисленными методами выглядит так:
arrayOfIngredients.set(1, "капуста")
arrayOfIngredients.get(1)
Функция set() принимает два параметра: индекс и значение. Мы указали, что элемент по индексу 1 нужно заменить значением “капуста”. Метод get() принимает только индекс и мы получаем это значение по индексу 1. Можете самостоятельно его распечатать в консоль.
Хорошо. Наконец, сейчас я продемонстрирую как обращаться ко всем значениям массива. Делать это мы будем с помощью перебора всех значений с распечаткой в консоль каждого из них. Итерация по массиву (как и по любому списку) необходима в случаях, когда нужно взаимодействовать со всеми элементами или его частью (например поиск, сортировка и т.д.). Это могут быть как простые строки и числа, так и объекты, но об этом немного позже.
Итак, для итерации по значениям будем использовать цикл for, разбираемый в прошлом уроке. Делается это довольно просто.
Пишем цикл for, в условии переменная-контейнер i берет элементы из переданного массива с ингредиентами. В теле пишем println(), где распечатываем i на каждой итерации. Запускаем и получаем список значений:
for (i in arrayOfIngredients) {
println(i)
}
Чтобы сделать вывод чуть элегантнее, доработаем оформление, чтобы получился пронумерованный список. Пишем слово “Ингредиент”, затем будем указывать порядковый номер. Для этого можно использовать индекс элемента. Узнаем индекс конкретного элемента через вызов функции indexOf() у массива. В параметры этого метода поставляем нужный элемент i. Функция возвращает целое число – индекс текущего элемента. Но так как индекс всегда начинается с нуля, выведется список 0, 1 , 2, 3, 4. Следовательно, там же нужно к индексу прибавлять единицу и делать это будем прямо в строке:
for (i in arrayOfIngredients) {
println("Ингредиент ${arrayOfIngredients.indexOf(i) + 1}: $i")
}
Вывод в консоль
Ингредиент 1: яйцо
Ингредиент 2: помидор
Ингредиент 3: зелень
Ингредиент 4: соль
Ингредиент 5: перец
Массивы обладают широким набором методов для взаимодействия, расширяя их возможности. Эти инструменты будем рассматривать далее.
Для тех, кто собрался стать Android-разработчиком
Пошаговая
схема
Описание процесса обучения от основ Kotlin до Android-разработчика
Бесплатные
уроки
Авторский бесплатный курс по основам языка программирования Kotlin
Обучающий
бот
Тренажер и самоучитель по Котлин – бесплатные тесты и практика