Loops A La Kotlin for Java Developers

Christian Vasquez - Jan 6 '18 - - Dev Community

Whenever we find something that has to be done multiple times or we want to find something in a group of values we rely on these wonderful friends we have at our disposal:

For loop

// Java

for (condition) {
    statement;
}
Enter fullscreen mode Exit fullscreen mode

For-each

// Java

for (TYPE item : items) {
    statement;
}
Enter fullscreen mode Exit fullscreen mode

While loop

// Java

while (condition) {
    statement;
}
Enter fullscreen mode Exit fullscreen mode

Do-while loop

// Java

do {
    statement;
} while (condition)
Enter fullscreen mode Exit fullscreen mode

The Kotlin Standard Library provides us with a handful of methods and classes to make our lives easier for common things like this.

Examples:

Disclaimers

  • The Java samples are from version < 8. The new Stream library provides similar higher order functions to what Kotlin offers (thanks @robertbutacu for the input).
  • These are simplified versions of the scenarios.

1) Imagine you are shopping on Amazon and you want to filter the products so that you only see the ones with 3 or more as their rating:

First, we will need a Product class, which will have name and rating as properties.

// Java

public class Product {
    private final int rating;
    private final String name;

    public Product(String name, int rating) {
        this.rating = rating;
        this.name = name;
    }

    public int getRating() {
        return rating;
    }

    public String getName() {
        return name;
    }
}
Enter fullscreen mode Exit fullscreen mode

I'll make a function that will filter our List of Product depending on the rating we pass in to it.

// Java

private static List<Product> filterByRating(List<Product> products, int rating) {
    List<Product> filteredProducts = new ArrayList<>();
    for (Product product : products) {
        if (product.getRating() >= rating) {
            filteredProducts.add(product);
        }
    }

    return filteredProducts;
}    
Enter fullscreen mode Exit fullscreen mode

Here we created another List of Products that will be filled up by the for-each block, but only if their rating is equal or higher than 3.

We will add this function to the Main class. Now we can use it like:

// Java

public class Main {

    public static void main(String[] args) {
        List<Product> products = new ArrayList<>();
        products.add(new Product("Pants", 2));
        products.add(new Product("Laptop", 4));
        products.add(new Product("Smartphone", 5));

        List<Product> productsWithThreeOrHigherRating = filterByRating(products, 3);

        // ...
    }

    // filteredByRating method would be here
}
Enter fullscreen mode Exit fullscreen mode

Great, now let's do the same A La Kotlin:

// Kotlin

class Product(val name: String, val rating: Int)
Enter fullscreen mode Exit fullscreen mode

We won't need a filterByRating() function, we will use the filter() method that every class that inherits from Iterable gets for free instead (like the List<> in this case).

// Kotlin

fun main(args: Array<String>) {
    val products = listOf(
            Product("Pants", 2),
            Product("Laptop", 4),
            Product("Smartphone", 5)
    )

    val productsWithThreeOrHigherRating = products.filter { it.rating >= 3 }

    // ...
}
Enter fullscreen mode Exit fullscreen mode
  • listOf() is a public function from the kotlin.collection package that allows any number of arguments, which types can be inferred automatically (they can even be of different types) and returns a List.
  • Each of the Product instances that we added to our products List does not require us to use the new keyword, like in Java, in fact, the new keyword doesn't exist in Kotlin.
  • We are using a Lambda expression for the products.filter method, which requires the use of { and }.
  • The it keyword is always present whenever we write a lambda expression with only a single argument. It's similar to this, but it refers to a single product inside our products List while we iterate over it, like in a for-each loop.
  • The whole it.rating >= 3 is called a predicate.

A predicate is a boolean-valued expression that is passed to another function as an argument for it to perform another action only when that expression is true.

2) Let's say we want to print all the names of our productsWithThreeOrHigherRating to check which are the Product we got:

// Java

public class Main {

    public static void main(String[] args) {
        // ...

        List<Product> productsWithThreeOrHigherRating = filterByRating(products, 3);

        for (Product product : productsWithThreeOrHigherRating) {
            System.out.println(product.getName());
        }

        // ...
    }
}
Enter fullscreen mode Exit fullscreen mode

Now A La Kotlin:

// Kotlin

fun main(args: Array<String>) {
    // ...

    val productsWithThreeOrHigherRating = products.filter { it.rating >= 3 }

    productsWithThreeOrHigherRating.forEach { println(it.name) }

    // ...
}
Enter fullscreen mode Exit fullscreen mode
  • forEach is a another function from Iterable (like the filter we used before) that takes a any argument as long as it's return type is Unit(which is similar to void in Java).
  • In this case we made use of the println() function that is a shorthand for System.out.println().
  • We make us of the it keyword again in our expression and we access the name property in order to println it.

3) Now, what if we want to know if there is at least 1 Product in inside our productsWithThreeOrHigherRating that has a rating value of 5?

I will make a function and call it hasAnyFiveRating:

// Java

public boolean hasAnyFiveRating(List<Product> products) {
    for (Product product : products) {
        if (product.rating == 5) {
            return true;
        }
    }

    return false;
}
Enter fullscreen mode Exit fullscreen mode

Now we can use it to do any sort of validation in our Main class:

// Java

public class Main {

    public static void main(String[] args) {
        // ...

        List<Product> productsWithThreeOrHigherRating = filterByStars(products, 3);

        if (hasAnyFiveRating(productsWithThreeOrHigherRating)) {
            // ...
        else {
            // ...
        }

        // ...
    }
}
Enter fullscreen mode Exit fullscreen mode

Now A La Kotlin:

// Kotlin

fun main(args: Array<String>) {
    // ...

    val productsWithThreeOrHigherRating = products.filter { it.rating >= 3 }

    val hasAnyFiveRating = productsWithThreeOrHigherRating.any { it.rating == 5 }
    if (hasAnyFiveRating) {
        // ...
    } else {
        // ...
    }

    // ...
}
Enter fullscreen mode Exit fullscreen mode

Pretty cool stuff, huh?

There are even more useful functions like these cooked into the language that you may be able to use in your projects. But that would make this post even bigger, so I'll let you research the rest.

Hopefully you learned something new with this post, and if you didn't congrats! You just wasted a few minutes of your life 👏.

But don't worry, you would probably be playing PlayerUnknown Battlegrounds right now like the other 3 million people around the globe (including me)... it's not like you would be saving the world anyways.

That's it from me.

Chris out! ✌️

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .