Read on for an introduction to the most important functions for predicates: all
, any
, none
, isEmpty
, isNotEmpty
, ifEmpty
, contains
, containsAll
, and their variants.
Predicate functions
all, any, none
//sampleStart inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean //sampleEnd
The all
method accepts a predicate and returns true
if every element satisfies the predicate, and false
otherwise. The some
method has the same input, but returns true
if at least one element satisfies the predicate, and false
otherwise.
Example
//sampleStart fun main() { val list = listOf(1, 2, 3, 4) list.all { it % 2 == 0 }.also(::println) // false list.any { it % 2 == 0 }.also(::println) // true } //sampleEnd
There are also variations of any
and none
that take no arguments, and return true
if the collection has at least one element and no elements, respectively.
Example
//sampleStart fun main() { val list = listOf(1) list.any().also(::println) // true list.none().also(::println) // false emptyList<Int>().none().also(::println) // true } //sampleEnd
isEmpty
, isNotEmpty
, ifEmpty
//sampleStart fun isEmpty(): Boolean inline fun <T> Collection<T>.isNotEmpty(): Boolean inline fun <C : Collection<*>, R> C.ifEmpty( defaultValue: () -> R ): R where C : R //sampleEnd
The isEmpty
method is not an extension, but defined directly on the Collection
interface. Predictably, it returns true
if the collection contains no elements. For List
, none
is an alias for isEmpty
. The opposite of isEmpty
is isNotEmpty
. There is also isNullOrEmpty
, which is defined on a nullable receiver:
//sampleStart inline fun <T> Collection<T>?.isNullOrEmpty(): Boolean //sampleEnd
Of interest is the ifEmpty
method, which allows us to substitute a different Collection
if the receiver is empty. Notice that the type of the return value is always the type of what is returned by defaultValue
, which can be a super-type of the receiver.
Example
//sampleStart fun main() { val list1 = emptyList<Int>() // List<Int> val list2 = listOf(1, 2, 3) // List<Int> list1.ifEmpty { listOf(4, 5.2, 3) }.also(::println) // List<Number> { 4, 5.2, 3 } list2.ifEmpty { listOf(4, 5.2, 3) }.also(::println) // List<Number> { 1, 2, 3 } } //sampleEnd
contains
, containsAll
//sampleStart operator fun <T> Iterable<T>.contains(element: T): Boolean inline fun <T> Collection<T>.containsAll( elements: Collection<T> ): Boolean //sampleEnd
We already know contains
from the chapter on operators. It can be invoked using the in
keyword. The containsAll
expands on this functionality by returning true
only if the receiver contains all the elements of the argument, and false
otherwise. Naturally, it is not an operator.
Example
//sampleStart fun main() { val list = listOf(1, 2, 3) list.contains(2).also(::println) // true println(2 in list) // true // listOf(1, 2) in list // Won't compile. Equivalent to list.contains(listOf(1, 2)) list.containsAll(listOf(1, 2)).also(::println) // true } //sampleEnd