Our Collection API (Kotlin Framework Class Hierarchy, Function Type, Predicate)

Designed By Hafiz Waleed Hussain

The easiest way to learn Kotlin Collection made your collection. In this series, we will create a class with the name “Our Collection.” That will contain all the methods which are given by Kotlin, but we will implement on our own. So once we will do practice, we will be more comfortable to use these powerful functions.

Motivation:

Before I start only, I am doing one experiment with my readers. Write a map function on your own. You can say fun ourMap(). I did this experiment, a long time ago with myself, and failed. After this, I did this experiment with my friends and colleagues and mostly failed. So do this experiment and if you can write that is good, and if not, then don’t lose your motivation, you are still a good developer.

Those who are not able to write this for them we will do an investigation of what happened. I feel when we are using these operators as chaining in our code base. A compiler and lambda expressions are helping us a lot. Like, try to write a map function but by using function reference or function type but not lambda.

data class Product(val name: String, val price: Int)

fun main() {
    val listOfProducts = listOf(Product("A", 1), Product("B", 2), Product("C", 3), Product("D", 4))
    val listOfPrices = listOfProducts.map { it.price }.toList()
}

As shown in above example try to replace map{} with map(::functionReference) or map(functionType)

If you can achieve then try groupBy function and try to change lambda with function reference or function type. You will feel what I am trying to convey. Now, I am writing above map example with function reference and with function type.

    
listOfProducts.map(::mapToPrice).toList()
fun mapToPrice(product: Product): Int = product.price

listOfProducts.map(mapType).toList()
val mapType :(Product) -> Int = {product -> product.price}

Introduction:

As we know we are going to create Our Collection also I shared with you my motivation. In perspective of these, we need some prerequisite. Some required prerequisite I will explain and some I am expecting reader already know.

Prerequisite:

  • Kotlin Collection Framework Class Hierarchy ( Will explain )
  • Function Type ( Will explain )
  • Function Reference
  • Lambda Expression
  • Predicate ( Will explain )
  • Extension Method
  • Higher-Order Function

Kotlin Collection Framework Class Hierarchy:

https://kotlinlang.org/docs/reference/collections-overview.html

As shown in the above diagram, Kotlin has this Collection Framework. In our case, we will not focus on Mutable API’s so for us. Things will be more comfortable, as shown below:

I always say the Creation of a diagram is easier than the implementation of that diagram in code. In our case, I will show you how this diagram is currently implemented in Kotlin, as shown below:

Try to remember this diagram that will help us a lot when we create Our Collection API’s.

Function Type:

Just like we have type in Java, int, float, dobule in the same way kotlin contain one type which is called function type. This type is compelling but sometimes take time to grab this concept.

Now, as in Java/Kotlin, I want to save the value of quantity. I will create a data type Int, which will keep this value as shown below:

val quantity: Int = 10

Now, in our program, I want to use this value. I will use a quantity variable, which is an Int type, as shown below:

val total = quantity * 20

Now, the same concept we are going to use with function type. I am going to create a multiple function type, as shown below:

val type1: () -> Unit = {}
val type2: () -> String = { "String" }
val type3: () -> Int = { 3 }
val type4: (Int) -> Unit = { value -> value }
val type5: (String) -> Unit = { value -> value }
val type6: (String, Int) -> String = { s, i -> "$s+$i" }

So you can see the different function types, how we defined in the above example. Next, we will see some useful function type.

val isEven: (Int) -> Boolean = { value -> value % 2 == 0 }

Just like quantity, I can use isEven anywhere I want, for example.

isEven(10)

So above will give me the answer true. I can use this isEven in the filter, as shown below:

ints.filter { isEven(it) }

We can use isEven as a function type in the filter, as shown below:

ints.filter(isEven)

This is a fantastic use of function type. Filter always asks for predicate and isEven is a predicate. We will discuss predicate later.

Function type also useful to replace interfaces. Like in Thread, we need to use Runnable interface as shown below:

val t = Thread(Runnable { })

But we can use function type also as shown below:

val runnable: () -> Unit = {}

val t = Thread(runnable)
t.start()

Predicate:

In simple words, a predicate is a statement about something which returns boolean. I am not going in the mathematical definition. Instead, I am going to share with you Java 8 predicate interface.

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    ...
}

As shown in the above code. That is a simple interface with a method test, which will take a generic param and return a boolean.

Now in Kotlin, we can say any function type which will take any value as param but return a boolean that always a predicate.

val type: (Int) -> Boolean = { return boolean }

This is a predicate. If you remember that is we used for isEven function type.

val isEven: (Int) -> Boolean = { value -> value % 2 == 0 }

I hope everyone knows what a predicate is. Again any function which is making some decision and returning boolean always a predicate. Now, this information will help us a lot in Our Collection API. But to make more clear I am going to share with you some predicate examples from Kotlin Collection API’s.

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

Wow, filter always asks a predicate. Now it’s time to explore more API’s.

fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean)
fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean)
fun <T> Iterable<T>.all(predicate: (T) -> Boolean)
fun <T> Iterable<T>.any(predicate: (T) -> Boolean)

I hope now, we will remember predicate.

Why we discussed all the above concepts:

Now once we are going to implement Our Collection API. We need to grasp these concepts. For example:

  • Kotlin Collection Framework Class Hierarchy
    • This will help us when we are going to create an Our Collection API. For example, we will get a performance boost if we know how hierarchy is working.
public fun <T> Iterable<T>.count(): Int {
    if (this is Collection) return size
    var count = 0
    for (element in this) checkCountOverflow(++count)
    return count
}

public inline fun <T> Collection<T>.count(): Int {
    return size
}
  • Function Type
    • All params of Our Collection API will function type.
  • Predicate
    • This will make our communication easy. Anywhere I will use this term first thing in your mind will be some function type which will return Boolean. The second thing in your mind this API will do some filtering for us in the Collection.

I hope you enjoyed the first part. From the next section, we will start writing Our Collection API by following Kotlin Collection API methods.

Next post: ourAll, ourAny ( Our Collection API like Kotlin Collection API )

Facebooktwitterredditpinterestlinkedinmailby feather

Leave a Reply

Your email address will not be published. Required fields are marked *

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