Выбор одного элемента
В Kotlin существует набор функций для извлечения отдельных элементов из коллекции.
Функции, описанные в этом разделе, применимы как к спискам, так и к множествам (Set
).
В определении списка сказано, что список - это упорядоченная коллекция. Следовательно, каждый элемент списка имеет свою позицию, которую вы можете использовать в качестве ссылки на этот элемент. В дополнение к функциям, описанным в этом разделе, списки предлагают более широкий набор способов извлечения и поиска элементов по индексам. Для получения дополнительной информации см. List: специфичные операции.
В свою очередь множество не является упорядоченной коллекцией по определению. Однако в Kotlin Set
хранит элементы в определённом порядке. Это может быть порядок вставки (как в LinkedHashSet
), естественный порядок сортировки (как в SortedSet
) или какой-либо другой порядок.
Но также порядок может быть и неизвестен. В таком случае элементы всё равно каким-то образом упорядочены, поэтому функции, которые полагаются на позиции элементов, по-прежнему возвращают свои результаты. Однако такие результаты непредсказуемы для конечного пользователя, если он не знает, какую из реализаций использует Set
.
Получение элемента по его позиции
Для получения элемента в определённой позиции существует функция
elementAt()
.
При вызове передайте ей целое число в качестве аргумента и она вернёт вам элемент коллекции, который находится в данной позиции. У первого элемента позиция равна 0
, а у последнего - (size - 1)
.
Функция elementAt()
полезна для использования с коллекциями, которые не предоставляют индексированный доступ. При работе с List
более идиоматично использовать оператор доступа по индексу (get()
или []
).
fun main() {
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.elementAt(3)) // four
// элементы хранятся в порядке возрастания
val numbersSortedSet = sortedSetOf("one", "two", "three", "four")
println(numbersSortedSet.elementAt(0)) // four
}
Также существуют полезные функции для получения первого и последнего элемента коллекции:
first()
и
last()
.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.first()) // one
println(numbers.last()) // five
}
Чтобы избежать исключений при обращении к несуществующим в коллекции элементам, используйте безопасные варианты функции elementAt()
:
* elementAtOrNull()
- возвращает null
, если указанная позиция выходит за границы коллекции.
* elementAtOrElse()
- дополнительно принимает лямбда-функцию. Когда происходит вызов с позицией, которая выходит за границы коллекции, elementAtOrElse()
возвращает результат выполнения лямбды.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.elementAtOrNull(5)) // null
println(numbers.elementAtOrElse(5) { index -> "The value for index $index is undefined"}) // The value for index 5 is undefined
}
Получение элемента по условию
Функции first()
и
last()
позволяют искать в коллекции элементы, соответствующие заданному предикату. При вызове функции first()
с предикатом, вы получите первый элемент, для которого предикат возвращает true
. В свою очередь функция last()
с предикатом вернёт последний элемент, соответствующий предикату.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.first { it.length > 3 }) // three
println(numbers.last { it.startsWith("f") }) // five
}
Если ни один элемент не соответствует предикату, обе функции выбросят исключение. Чтобы этого избежать, используйте firstOrNull()
и
lastOrNull()
: эти функции вернут null
, если элементы не найдены.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.firstOrNull { it.length > 6 }) // null
}
Также вы можете использовать нижеперечисленные функции, если их имена лучше подходят для вашей ситуации:
* find()
вместо firstOrNull()
* findLast()
вместо lastOrNull()
fun main() {
val numbers = listOf(1, 2, 3, 4)
println(numbers.find { it % 2 == 0 }) // 2
println(numbers.findLast { it % 2 == 0 }) // 4
}
Получение элемента с помощью селектора
Если перед извлечением элемента вы хотите его преобразовать, то используйте функцию
firstNotNullOf()
.
Она сочетает в себе два действия:
- Преобразует коллекцию с помощью функции селектора.
- Возвращает первое значение, не равное null
.
Функция firstNotNullOf()
бросает исключение NoSuchElementException
, если не было найдено значения, отличного от null
. Чтобы этого избежать, используйте функцию
firstNotNullOfOrNull()
, которая в этом случае вернёт null
.
fun main() {
val list = listOf<Any>(0, "true", false)
// Преобразует каждый элемент в строку и возвращает первый элемент с нужной длиной.
val longEnough = list.firstNotNullOf { item -> item.toString().takeIf { it.length >= 4 } }
println(longEnough) // true
}
Получение случайного элемента
Функция random()
позволяет получить произвольный элемент коллекции. Её можно вызывать без аргументов, либо с объектом
Random
.
fun main() {
val numbers = listOf(1, 2, 3, 4)
println(numbers.random()) // 1
}
Если коллекция пуста, то функция random()
выбросит исключение. Чтобы вместо исключения получать null
, используйте randomOrNull()
.
Проверка на наличие элемента
Чтобы проверить есть ли в коллекции определённый элемент, используйте функцию
contains()
. Функция вернёт true
, если элемент, переданный ей в качестве аргумента, есть в коллекции.
Также эту функцию можно использовать в форме оператора при помощи ключевого слова in
.
Для проверки на наличие в коллекции сразу нескольких элементов используйте функцию
containsAll()
. В качестве аргумента передайте ей коллекцию искомых элементов.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.contains("four")) // true
println("zero" in numbers) // false
println(numbers.containsAll(listOf("four", "two"))) // true
println(numbers.containsAll(listOf("one", "zero"))) // false
}
Помимо прочего, вы можете проверить, содержит ли коллекция какие-либо элементы, вызвав
isEmpty()
или
isNotEmpty()
.
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.isEmpty()) // false
println(numbers.isNotEmpty()) // true
val empty = emptyList<String>()
println(empty.isEmpty()) // true
println(empty.isNotEmpty()) // false
}