Cтандартные функции

Cтандартные функции


В главное меню


apply

apply можно использовать, чтобы уменьшить количество повторений при подготовке объекта к использованию.

val menuFile = File("menu-file.txt")
menuFile.setReadable(true)
menuFile.setWritable(true)
menuFile.setExecutable(false)

Используя apply, то же самое можно реализовать меньшим количеством кода:

val menuFile = File("menu-file.txt").apply {
    setReadable(true)
    setWritable(true)
    setExecutable(false)
}

Такое поведение иногда называют ограничением относительной области видимости (relative scoping), потому что вызовы всех функций внутри лямбды относятся к объекту-приемнику


let

определяет переменную в область видимости заданной лямбды и позволяет использовать ключевое слово it для ссылки на нее

val firstItemSquared = listOf(1,2,3).first().let {
    it * it
}

Без let пришлось бы присвоить первый элемент переменной, чтобы выполнить умножение:

val firstElement = listOf(1,2,3).first()
val firstItemSquared = firstElement * firstElement

Взгляните на следующий пример, который изменяет текст приветствия в зависимости от того, узнал трактирщик игрока или нет

fun formatGreeting(vipGuest: String?): String {
    return vipGuest?.let {
        "Welcome, $it. Please, go straight back - your table is ready."
    } ?: "Welcome to the tavern. You'll be seated soon."
}


run

Функция run похожа на apply, точно так же ограничивая относительную область видимости, но не возвращает объект-приемник.

Например, вот как можно проверить наличие конкретной строки в файле:

val menuFile = File("menu-file.txt")
val servesDragonsBreath = menuFile.run {
    readText().contains("Dragon's Breath")
}

run может также использоваться для выполнения ссылки на функцию относительно объекта-приемника. Вы использовали ссылки на функции в главе 5: вот пример, как сделать это с run:

fun nameIsLong(name: String) = name.length >= 20
"Madrigal".run(::nameIsLong) // Ложь
"Polarcubis, Supreme Master of NyetHack".run(::nameIsLong) // Истина

Выгоды от использования run становятся более очевидными, когда требуется вызвать несколько функций: вызов цепочкой с помощью run проще читать и анализировать.

fun nameIsLong(name: String) = name.length >= 20
fun playerCreateMessage(nameTooLong: Boolean): String {
    return if (nameTooLong) {
        "Name is too long. Please choose another name."} 
    else {
        "Welcome, adventurer"
    }
}
"Polarcubis, Supreme Master of NyetHack"
    .run(::nameIsLong)
    .run(::playerCreateMessage)
    .run(::println)


with

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

val nameTooLong = with("Polarcubis, Supreme Master of NyetHack") {
    length >= 20
}

Более того, рекомендуем избегать with и использовать вместо нее run.

val list = mutableListOf<Int>()
with(list) {
    for(i in 0 until 1000) {
        add((Math.random() * 100).toInt())
    }
    val sum = sum()
    val average = average()
    val max = maxOrNull()
    val min = minOrNull()
    val first = first()
    val last = last()
    println("$sum\n$average\n$max\n$min\n$first\n$last")
}


also

Функция also похожа на функцию let. Как и let, also передает объект-приемник как аргумент в лямбду. Но есть одно большое различие между let и also: вторая возвращает объект-приемник, а не результат лямбды.

Это делает also особенно полезной для добавления различных побочных эффектов. Пример ниже дважды вызывает also для выполнения двух разных операций: первая выводит имя файла, а вторая записывает содержимое файла в переменную fileContents.

var fileContents: List<String>
File("file.txt")
    .also {
        print(it.name)
    }.also {
        fileContents = it.readLines()
    }
}

Так как also возвращает объект-приемник, а не результат лямбды, с ее помощью можно вызвать длинную цепочку функций относительно оригинального объекта-приемника.

filter

===============================1========================
Отфильтрует числа, которые делятся на 3

val list = listOf(1,2,3,4,5,6,7)
list.filter{ it % 3 == 0 }

===============================2========================
Отфильтрует числа с элементами null

val nullableList : List<Int?> = listOf(1, 2, 5, 8, null, 9, 12)
println(nullableList.filter { x -> x != null && x % 3 == 0 })

===============================3========================
Фильтр по возрасту

println(people.filter { it.age > 30 })
val people = listOf(
        Person("Alice", 29),
        Person("Bob", 30),
        Person("Carol", 31)
)

===============================4========================
Фильтр по возрасту
val people = listOf(
        Person("Alice", 29),
        Person("Bob", 30),
        Person("Carol", 31)
)

println(people.filter { it.age == 60 }) - ошибка! элемента такого нет
people.firstOrNull { it.age == 60 } - вернет null если ничего не найдёт


any

Позволяет проверить соответствует ли заданному критерию элемент из коллекции. Если соответствует, то результат да.

val people = listOf(
        Person("Alice", 29),
        Person("Bob", 30),
        Person("Carol", 31)
)

people.any{it.age == 30} //true


count

Посчитает количество объектов в списке
people.count()

Можно через предикат
people.count{it.age > 30}
посчитаем кол-во элементов с заданным условием


find

Выведет на экран элемент, который соответсвует данному условию.
people.find { it.age == 31 && it.name.contains('o') }


groupBy

Группировка по возрасту.
people.groupBy { it.age }

Результат:
{
30=[Person(name=Alice, age=30), Person(name=Bob, age=30)], 
60=[Person(name=Buba, age=60)], 
31=[Person(name=Carol, age=31)]
}

Возвращает мапу, можно вывести значения

people.groupBy { it.age }.keys


associateBy

То же что и groupBy только сохраняется один элемент в каждом возрасте (последний) а не все.

people.associateBy { it.age }


partition

Создает коллекции, которые соответствуют условию или не соответствуют.

people.partition { it.age > 30 }

Результат:
(
[Person(name=Buba, age=60), Person(name=Carol, age=31)], 

[Person(name=Alice, age=30), Person(name=Bob, age=30)]
)


all

Report Page