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 apublic
function from thekotlin.collection
package that allows any number of arguments, which types can be inferred automatically (they can even be of different types) andreturns
a List. - Each of the Product instances that we added to our
products
List does not require us to use thenew
keyword, like in Java, in fact, thenew
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 tothis
, but it refers to a singleproduct
inside ourproducts
List while we iterate over it, like in afor-each
loop. - The whole
it.rating >= 3
is called apredicate
.
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 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) }
// ...
}
-
forEach
is a another function from Iterable (like thefilter
we used before) that takes a any argument as long as it's return type is Unit(which is similar tovoid
in Java). - In this case we made use of the
println()
function that is a shorthand forSystem.out.println()
. - We make us of the
it
keyword again in our expression and we access thename
property in order toprintln
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;
}
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.