Что делают функции all и any в Kotlin и как их использовать для проверки условий
Что проверяют
Знаете ли вы стандартные предикаты коллекций и их краевые случаи. Это короткий вопрос, по которому видно, пишете ли вы на Kotlin или на Java со скобками от Kotlin: вместо цикла с флагом и break человек либо сразу берёт готовую функцию, либо нет.
Как отвечать
all возвращает true, если предикат верен для всех элементов, any возвращает true, если хотя бы для одного. Обе останавливаются на первом решающем элементе.
val list = listOf(1, 2, 3)
list.all { it > 0 } // true
list.any { it % 2 == 0 } // true
list.none { it > 5 } // true
list.any() // то же, что isNotEmpty()
emptyList<Int>().all { it > 100 } // true
emptyList<Int>().any { it > 100 } // falseКраевой случай стоит назвать самому: на пустой коллекции all даёт true, потому что опровергающего элемента нет, а any даёт false. Рядом живёт none, зеркальное к any.
Дальше полезно добавить, что обе функции объявлены как inline, поэтому лямбда не превращается в объект и вызывать их в горячем коде не страшно, а return внутри выходит из внешней функции. Работают они на любом Iterable, на Sequence, на Map (элемент это Map.Entry) и на строках.
В Android это обычная валидация формы fields.all { it.isValid } или проверка выданных разрешений.
Где спотыкаются
Не помнят про пустую коллекцию. Если список правил пуст, rules.all { it.matches(x) } пропустит что угодно, и фильтр молча перестанет работать. Когда пустота недопустима, пишут isNotEmpty() && all { ... }.
Путаются в отрицании. !list.all { it.isValid } означает «хотя бы один невалиден», а не «все невалидны». Читается это плохо, поэтому берут any { !it.isValid } или none { it.isValid }.
Пишут list.filter { ... }.isNotEmpty() вместо any. Создаётся промежуточный список, коллекция обходится целиком, и короткое замыкание теряется: на длинных списках разница заметна.