ourAll, ourAny ( Our Collection API like Kotlin Collection API )

Designed By Hafiz Waleed Hussain

Those who are new to this series of posts. We started Our Collection API framework like the Kotlin once. You can consult with our first post Our Collection API (Kotlin Framework Class Hierarchy, Function Type, Predicate)

In this post, we are going to create two methods from Kotlin Collection API all and any. We will say ourAll() and ourAny() methods.

all():

What is “all” method? According to Kotlin documentation
Returns `true` if all elements match the given [predicate].

For example, I have the data of posts. I want to check is all userId’s greater than 0.

fun main() {
    val posts = loadData()
    println(posts.all { it.userId > 0 })
}

Output: true

If you remember predicate, this method is asking a predicate param. Now, we made the promise we will not use lambda. Instead, we will use function or function type so we can grab more authentic knowledge before going to the next paragraph. Try to write the same function with function and with function type with some random data object.

fun main() {
    val posts = loadData()
    val allPredicateFunctionType: (Post) -> Boolean = { post -> post.id > 0 }
    println(posts.all(allPredicateFunctionType))
}
fun main() {
    val posts = loadData()
    println(posts.all(::allPredicateFunction))
}

fun allPredicateFunction(post: Post): Boolean = post.id > 0

Use case of all():

If you have code something like below in your codebase, you can replace that with all method.

fun main() {
    val posts = loadData()
    val isTrue = someFunction(posts)
}

fun someFunction(posts: List<Post>): Boolean {
    var isAllUserIdsGreaterThenZero = false
    for (post in posts) {
        if (post.id > 0)
            isAllUserIdsGreaterThenZero = true
        else {
            isAllUserIdsGreaterThenZero = false
            break
        }
    }
    return isAllUserIdsGreaterThenZero
}

// Replcae with below

fun main() {
    val posts = loadData()
    val isTrue = posts.all { it.id > 0 }
}
fun main() {
    val posts = loadData()
    val isTrue = someFunction(posts)
}

fun someFunction(posts: List<Post>): Boolean {
    for (post in posts) {
        if (post.id > 0) {
        } else
            return false
    }
    return true
}

// Replcae with below

fun main() {
    val posts = loadData()
    val isTrue = posts.all { it.id > 0 }
}

Also, there is one more clue when you should use all() method. When you have a list, and you want a Boolean answer with some condition, and that condition should be applied to all list data objects.

val functionType : (Post) -> Boolean = { condition }
data.all(functionType)

ourAll():

It’s time to implement ourAll() method. That is straight forward. But try to think a little bit.
First, this method needs a predicate as param. Also, we are going to write a generic method so that predicate should have a generic param and will return Boolean.
Now I am going to write first this predicate. I hope you guys already wrote this :).

predicate : (T)-> Boolean

Next, we will make this method for all collections. So we can implement as an Extension Method with Iterable according to our Kotlin Collection Class Hierarchy.

fun <T> Iterable<T>.ourAll()

Next, it’s time to add a predicate as param.

fun <T> Iterable<T>.ourAll(predicate : (T)-> Boolean)

Next, we already know this function will return us a Boolean. So it’s time to add a Boolean as a return type.

fun <T> Iterable<T>.ourAll(predicate : (T)-> Boolean) : Boolean

Now, we need to focus on the body. So as we know, we need to iterate on all elements. It’s mean there will be a loop and second, we need to call our predicate on our all values. So try first on your own. I am going to write; next, it’s body according to this description.

fun <T> Iterable<T>.ourAll(predicate : (T)-> Boolean) : Boolean{
    for( element in this){
        if(predicate(element) == false)    
            return false
    }
    return true
}

We can improve the if condition, as shown below:

fun <T> Iterable<T>.ourAll(predicate : (T)-> Boolean) : Boolean{
    for( element in this){
        if(!predicate(element))
            return false
    }
    return true
}

Now ourAll method is ready. It’s time to test with the same data. You can also try on your data.

fun main() {
    val posts = loadData()
    println(posts.all { it.userId > 0 })
    println(posts.ourAll { it.userId > 0 })
}

Output: true
true

Yes, we completed our first method. Now, you can compare with Kotlin implementation. I am happy Kotlin is open source so we can check. I am going to copy-paste Kotlin implementation of 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
}

This method is more efficient, but our method is not wrong. Instead, our method is also suitable :).

Now I updated ourAll method as shown below:

inline fun <T> Iterable<T>.ourAll(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return true
    for (element in this) if (!predicate(element)) return false
    return true
}

any():

Next is any() method from Kotlin API. There are two flavors of any() method available in Kotlin API. First, we will explore any() method with predicate as param. It’s time to check this method documentation.
Returns `true` if at least one element matches the given [predicate].

This is a vice versa of all() method. In all() we remember condition should be valid for all data objects of the list. But in case of any(), we are expecting if at least one data object is valid with the condition then return true.

fun main() {
    val posts = loadData()
    println(posts.any { it.userId > 5 })
}

In my data, I have some users with id 1,2,3,4,5 but my output is true with any() because some of my users also have id 6,7,8,9.
Next, time to use this method with function type and with function.

fun main() {
    val posts = loadData()
    val functionType: (Post) -> Boolean = { post-> post.userId > 5 }
    println(posts.any(functionType))
}
fun main() {
    val posts = loadData()
    println(posts.any(::function))
}

fun function(post: Post) : Boolean = post.userId > 5

Use case of any():

Same like all() but in vice versa. So I am only writing code if you observe some code like this you can refactor to any.

fun main() {
    val posts = loadData()
    val isTrue = someFunction(posts)
}

fun someFunction(posts: List<Post>): Boolean {
    var b = true
    for (post in posts) {
        if (post.id > 5) {
            b = true
            break
        } else {
            b = false
            
        }
    }
    return b
}
// Replcae with below

fun main() {
    val posts = loadData()
    val isTrue = posts.any { it.id > 5 }
}
fun main() {
    val posts = loadData()
    val isTrue = someFunction(posts)
}

fun someFunction(posts: List<Post>): Boolean {
    for (post in posts) {
        if (post.id > 5)
            return true
    }
    return false
}

// Replcae with below

fun main() {
    val posts = loadData()
    val isTrue = posts.any { it.id > 5 }
}

ourAny():

It’s time to implement ourAny() method. Same like ourAll method. We need a predicate with generic param and will return Boolean.

predicate : (T)-> Boolean

Next, will work this method on iterable as ourAll method.

fun <T> Iterable<T>.ourAny(predicate : (T)-> Boolean)

Next, the method should return Boolean.

fun <T> Iterable<T>.ourAny(predicate : (T)-> Boolean) : Boolean

It’s time to write a body. Again the body will be the same only difference will be a condition. So this time try first to write on your own :).

fun <T> Iterable<T>.ourAny(predicate: (T) -> Boolean): Boolean {
    for (element in this) {
        if (predicate(element))
            return true
    }
    return false
}

Now, it’s time to run this method.

fun main() {
    val posts = loadData()
    println(posts.any { it.id > 5 })
    println(posts.ourAny { it.id > 5 })
}

Output: true
true

Before comparing with Kotlin implementation, I think we can improve our method performance in some cases :).

fun <T> Iterable<T>.ourAny(predicate: (T) -> Boolean): Boolean {
    if(this is Collection && isEmpty()) return false
    for (element in this) if (predicate(element)) return true
    return false
}

Now, it’s time to compare with Kotlin implementation.

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
}

Wow, we have the most efficient ourAny method implementation as we can see Kotlin API also implemented in the same way :P.

As I share with you, Kotlin has two flavors of any() method. It’s time to explore the second flavor of any() method.

The second flavor of any():

This implementation of any confuses me a lot in the start. Because this implementation has no params, before going to discuss more, we will read the documentation of this method in Kotlin API.
Returns `true` if collection has at least one element.

Example time:

fun main() {
    val listOfInts = listOf(1, 2, 3)
    println(listOfInts.any())
    val listOfFloats = listOf<Float>()
    println(listOfFloats.any())
}

Output: true
false

According to the definition. if the list contains at least one element this will return us true as we can see the output above.

Use case of any():

Anywhere you want to determine list contain data or not you can use this method. Instead, I am writing some code examples, if you find out something like that you can replace with any().

fun main() {
    val posts = loadData()
    if(!posts.isEmpty()){
    }
    // Replace with below
    if(posts.any()){
    }
}
fun main() {
    val posts = loadData()
    if(posts.isNotEmpty()){
    }
    // Replace with below
    if(posts.any()){
    }
}
fun main() {
    val posts = loadData()
    if (posts.size > 0) {
    }
    // Replace with below
    if (posts.any()) {
    }
}

It’s time to implement ourAny() method.

ourAny():

This implementation should be straight forward.

fun <T> Iterable<T>.ourAny(): Boolean

What about the body? Try to implement on your own. One tip, try to think about the class hierarchy and their methods. Then you can achieve the most efficient body for the first time.

fun <T> Iterable<T>.ourAny(): Boolean {
    if (this is Collection) return !isEmpty()
    return iterator().hasNext()
}

This is amazing. Please take some time and read the above implementation. This will take some time but will make sense, and you will feel the Wow moment :).

It’s time to use ourAny() method:

fun main() {
    val posts = loadData()
    println(posts.any())
    println(posts.ourAny())
}

Output: true
true

It’s time to check Kotlin implementation. By the way, I also learn my implementation from Kotlin, so that is why both look like the same.

public fun <T> Iterable<T>.any(): Boolean {
if (this is Collection) return !isEmpty()
return iterator().hasNext()
}

Until now code is available on Github commit.
Whole OurCollection GitHub repo.

Conclusion:

I hope you enjoy the implementation of these methods. For now, there is no conclusion, :). See you in the next part.

Facebooktwitterredditpinterestlinkedinmailby feather

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.