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;
}
For-each
// Java
for (TYPE item : items) {
statement;
}
While loop
// Java
while (condition) {
statement;
}
Do-while loop
// Java
do {
statement;
} while (condition)
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;
}
}
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;
}
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
}
Great, now let's do the same A La Kotlin:
// Kotlin
class Product(val name: String, val rating: Int)
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 }
// ...
}
-
listOf()is apublicfunction from thekotlin.collectionpackage that allows any number of arguments, which types can be inferred automatically (they can even be of different types) andreturnsa List. - Each of the Product instances that we added to our
productsList does not require us to use thenewkeyword, like in Java, in fact, thenewkeyword doesn't exist in Kotlin. - We are using a Lambda expression for the
products.filtermethod, which requires the use of{and}. - The
itkeyword is always present whenever we write a lambda expression with only a single argument. It's similar tothis, but it refers to a singleproductinside ourproductsList while we iterate over it, like in afor-eachloop. - The whole
it.rating >= 3is called apredicate.
A
predicateis a boolean-valued expression that is passed to another function as an argument for it to perform another action only when that expression istrue.
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());
}
// ...
}
}
Now A La Kotlin:
// Kotlin
fun main(args: Array<String>) {
// ...
val productsWithThreeOrHigherRating = products.filter { it.rating >= 3 }
productsWithThreeOrHigherRating.forEach { println(it.name) }
// ...
}
-
forEachis a another function from Iterable (like thefilterwe used before) that takes a any argument as long as it's return type is Unit(which is similar tovoidin Java). - In this case we made use of the
println()function that is a shorthand forSystem.out.println(). - We make us of the
itkeyword again in our expression and we access thenameproperty in order toprintlnit.
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;
}
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 {
// ...
}
// ...
}
}
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 {
// ...
}
// ...
}
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.
Top comments (3)
That comparison is not quite fair UNLESS you're using any Java version < 8. Java now has the Streams library which provides some higher functions. Generally, more code is required to be written that one would in Kotlin/Scala, but it's still there.
Thanks for replying, Robert!
I'll update the post accordingly.
I continue to be amazed that Kotlin and Swift have so many similarities, yet were developed completely independently of one another, and had their inception on the same month of the same year. On opposite sides of the world.
I can only speculate that Andrey Breslav and Chris Lattner operate on the same wavelength.