Blog / April 20, 2021 / 6 mins read / By Suneet Agrawal

any(), none() & all() : Kotlin

Kotlin is a powerful language that reduces a lot of boilerplate code required to perform basic operations in comparison to Java. The classic examples for the same are any, non and all functions which were added to the Iterable interface and Map interface.

Let try to understand what do they do, why they are required and when to use them. But before we begin, I am assuming a basic knowledge of Map, Set and List.

Any Set or List implementation implements Collection interface (indirectly) which extends Iterable and any Map implementation implement Map interface. All three of them are used to store similar data types with different benefits among the three.

The List provides the functionality to maintain the ordered collection. whereas Set and Map don’t provide the ordering. Both of them provides uniqueness but Map is a key-value pair mapping.

In short, all three of them are used to store data/objects of similar types.

Since the collection is involved, filtering will be required to iterate the data faster. To make this filter easier, Kotlin has added a few functions as an extension function to Iterable as well as Map.

Let look at them one by one.

Any

Any is a function that is added as an extension to Iterable and Map interfaces, which take a higher-order function as param to predicate the condition and return Boolean as true, if any of the items in List, Set or Map confirms that condition, else return false.

val list = listOf("one", "two", "three", "four")
val set = setOf("one", "two", "three", "four")
val map = mapOf(1 to "one", 2 to "two", 3 to "three", 4 to "four")

println(list.any { it.endsWith("e") })    // true
println(set.any { it.endsWith("e") })    // true
println(map.any { it.value.endsWith("e") })    // true

Let’s look at the extension function any, defined in Kotlin

/**
 * Returns `true` if at least one element matches the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.anyWithPredicate
 */
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return false
    for (element in this) if (predicate(element)) return true
    return false
}


/**
 * Returns `true` if at least one entry matches the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.anyWithPredicate
 */
public inline fun <K, V> Map<out K, V>.any(predicate: (Map.Entry<K, V>) -> Boolean): Boolean {
    if (isEmpty()) return false
    for (element in this) if (predicate(element)) return true
    return false
}

None

Similar to Any, None is a function that is added as an extension to Iterable and Map interfaces, which also takes a higher-order function as param to predicate the condition and return Boolean as true if none of the items in List, Set or Map confirms that condition, else return false.

val list = listOf("one", "two", "three", "four")
val set = setOf("one", "two", "three", "four")
val map = mapOf(1 to "one", 2 to "two", 3 to "three", 4 to "four")

println(list.none { it.endsWith("e") })    //false
println(set.none { it.endsWith("e") })    //false
println(map.none { it.value.endsWith("e") })    //false

Let’s look at the extension function none, defined in Kotlin

/**
 * Returns `true` if no elements match the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.noneWithPredicate
 */
public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return true
    for (element in this) if (predicate(element)) return false
    return true
}

/**
 * Returns `true` if no entries match the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.noneWithPredicate
 */
public inline fun <K, V> Map<out K, V>.none(predicate: (Map.Entry<K, V>) -> Boolean): Boolean {
    if (isEmpty()) return true
    for (element in this) if (predicate(element)) return false
    return true
}

All

Similar to Any and None, All is a function that is added as an extension to Iterable and Map interfaces, which also takes a higher-order function as param to predicate the condition and return Boolean as true if all of the items in List, Set or Map confirms that condition, else return false.

val list = listOf("one", "two", "three", "four")
val set = setOf("one", "two", "three", "four")
val map = mapOf(1 to "one", 2 to "two", 3 to "three", 4 to "four")

println(list.all { it.endsWith("e") })    //false
println(set.all { it.endsWith("e") })    //false
println(map.all { it.value.endsWith("e") })    //false

Let’s look at the extension function all, defined in Kotlin

/**
 * Returns `true` if all elements match the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.all
 */
public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return true
    for (element in this) if (!predicate(element)) return false
    return true
}


/**
 * Returns `true` if all entries match the given [predicate].
 * 
 * @sample samples.collections.Collections.Aggregates.all
 */
public inline fun <K, V> Map<out K, V>.all(predicate: (Map.Entry<K, V>) -> Boolean): Boolean {
    if (isEmpty()) return true
    for (element in this) if (!predicate(element)) return false
    return true
}

Any and None without any params

Any and None functions also have an overload to both Iterable and Map interfaces which don’t take any param but just check if the collection is empty or not.

Any returns true if the collection is not empty whereas None return true if the collection is empty.

val list = listOf("one", "two", "three", "four")
val set = setOf("one", "two", "three", "four")
val map = mapOf(1 to "one", 2 to "two", 3 to "three", 4 to "four")

println(list.any())    //true
println(set.any())    //true
println(map.any())    //true

println(list.none())    //false
println(set.none())    //false
println(map.none())    //false

Let’s look at the extension functions, defined in Kotlin

/**
 * Returns `true` if collection has at least one element.
 * 
 * @sample samples.collections.Collections.Aggregates.any
 */
public fun <T> Iterable<T>.any(): Boolean {
    if (this is Collection) return !isEmpty()
    return iterator().hasNext()
}


/**
 * Returns `true` if map has at least one entry.
 * 
 * @sample samples.collections.Collections.Aggregates.any
 */
public fun <K, V> Map<out K, V>.any(): Boolean {
    return !isEmpty()
}

/**
 * Returns `true` if the collection has no elements.
 * 
 * @sample samples.collections.Collections.Aggregates.none
 */
public fun <T> Iterable<T>.none(): Boolean {
    if (this is Collection) return isEmpty()
    return !iterator().hasNext()
}

/**
 * Returns `true` if the map has no entries.
 * 
 * @sample samples.collections.Collections.Aggregates.none
 */
public fun <K, V> Map<out K, V>.none(): Boolean {
    return isEmpty()
}

Benefits of using these functions

There is no difference in the implementation but since these are inbuild inline function, you don’t have to write the entire iteration and condition check on your own. Please note that there is no difference in time or space complexity also.

The only reason I wrote about this as a blog is because I feel I am lazy and prefers to use all inbuild functions to write fewer lines of code. :) These were a few of them.

Comments