Kotlin Koans—Part 19

This section of the Kotlin Koans tutorial continued onward with Kotlin’s collection API enhancement. The challenge in this section use to total the price of all products a customer purchased. Here is the code

fun Customer.getTotalOrderPrice(): Double {
    // Return the sum of prices of all products that a customer has ordered.
    // Note: a customer may order the same product for several times.
    return orders.sumByDouble { it.products.sumByDouble { it.price } }
}

The collection API in Kotlin has a sumByDouble method, which takes a lambda expression. The lambda let’s developers chain function calls. In this case, each Customer had a collection of Products in each Order. To get the price of all Products ordered, I needed the sum of the price of all products in a order. This was easy enough to do because I just made a nested call to sumByDouble on it.products and then told it to sum on it.price.

Here is Java code that solves the same problem.

public static double getTotalOrderPrice(Customer customer){
    return customer
            .getOrders()
            .stream()
            .mapToDouble(
                    order -> order.getProducts()
                                    .stream()
                                    .mapToDouble(Product::getPrice)
                            .sum())
            .sum();
}

You can click here to see Part 18

Advertisements

Kotlin Koans—Part 18

This portion of the Kotlin Koans tutorial deals with sorting a collection functionally. As usual with Kotlin, this wasn’t a very difficult problem. As a matter of fact, it’s only one line of code.

fun Shop.getCustomersSortedByNumberOfOrders(): List {
    return customers.sortedBy { it.orders.size }
}

We basically just call the sortedBy method and place the property we want to sort by inside of the curly braces { }. In this case, I wanted to sort by the number of orders my hypothetical customer placed, so I used it.orders.size.

Just for kicks, I decided to try this in Java 8 to see the difference.

public static List getCustomersSortedByNumberOfOrders(Shop shop){
    return shop.getCustomers()
            .stream()
            .sorted(Comparator.comparingInt(customer -> customer.getOrders().size()))
            .collect(Collectors.toList());
}

Once again, we can do the same thing in Java that we can do in Kotlin at the expense of more verbosity. Also, I think in this case, the Java approach is more difficult to learn and more prone to errors since we are chaining a bunch of functions together to achieve the same result that we can do in one line of Kotlin code.

You can click here to see Part 17

Kotlin Koans—Part 17

This part of Kotlin Koans continues to build on the features Kotlin offers on collection. Most of these methods will look familiar to people who have worked with Java 8 streams.

In this portion of the tutorial, I had to work with the maxBy method. It’s a nice little shortcut method to find an item based on a property. There is also a companion minBy.

fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? {
    // Return a customer whose order count is the highest among all customers
    return customers.maxBy { it.orders.size }
}

fun Customer.getMostExpensiveOrderedProduct(): Product? {
    // Return the most expensive product which has been ordered
    return orderedProducts.maxBy { it.price }
}

I was curious about what it would take to solve this problem in Java. Here is what I came up with.

public static Optional getCustomerWithMaximumNumberOfOrders(Shop shop){
    return shop.getCustomers().stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()));
}

I can’t say it was too brutal, but I think maxBy is much easier to read and understand as opposed to stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()))

You can click here to see Part 16

Kotlin Koans—Part 16

This portion of the Kotlin Koans tutorial continued with collection operations. Again, many of these operations are available in JDK8, but are missing in Android Java and previous versions of JDK. I got a few different demonstrations about what you can do with Kotlin here.

Operator Overloading

Kotlin supports operator overloading. I think this was a good move. C++ has operator overloading, but it was left out in Java. At the time, some people brought up that operator overloading was a source of bugs and it impacted code readability. I used to be one of those people, but frankly, I have been swayed back towards operator overloading. Operator overloading cuts down on verbosity in your code, and I can’t truthfully say I have seen additional bugs do to operator overloading.

Here is the first portion of Kotlin code

fun Customer.isFrom(city: City): Boolean {
    // Return true if the customer is from the given city
    return this.city == city
}

All

Kotlin collections have an all { } method that accepts a predicate. You can use it check if all items in a collection match the criteria specified in the predicate.

fun Shop.checkAllCustomersAreFrom(city: City): Boolean {
    // Return true if all customers are from the given city
    return customers.all { it.city == city }
}

Any

The any { } method is similar to all, but only one item in the collection has to match the predicate for it to return true.

 fun Shop.hasCustomerFrom(city: City): Boolean {
    // Return true if there is at least one customer from the given city
    return customers.any{ it.city == city }
}

Count

Kotlin collections have a count method also that returns the number of items that match the criteria provided in the predicate.

fun Shop.countCustomersFrom(city: City): Int {
    // Return the number of customers from the given city
    return customers.count { it.city == city }
}

Find Any

We also have a find any method which returns an item that matches the criteria in the predicate.

fun Shop.findAnyCustomerFrom(city: City): Customer? {
    // Return a customer who lives in the given city, or null if there is none
    return customers.find { it.city == city }
}

it

You may have noticed it popping up in all of these lambda expressions. As long as a SAM interface has only one parameter, developers can use a special it variable to refer to that parameter.

You can click here to see Part 15

Kotlin Koans—Part 15

Kotlin supports API that is similar to what is offered by Java 8 Streams. In this portion of the Kotlin Koans tutorial, I had to work with filtering and mapping. As an added bonus, I saw a good use case for Kotlin’s operator overloading capabilities and it’s collection transformation capabilities.

Here is the Kotlin code

fun Shop.getCitiesCustomersAreFrom(): Set {
    return customers.map { it.city }.toSet()
}

fun Shop.getCustomersFrom(city: City): List {
    return customers.filter { it.city == city }
}

The first function has us extracting all cities out the customers. In this example, customer has a city property. We can therefore us the map function to drill down to the city property on customer and gather than into a collection. Once we have our customers, we can use the toSet() method to transform the collection into a set.

The second function has us using a predicate to filter customers by city. Kotlin has operator overloading so we can use the == to compare object equality in Kotlin rather than reference equality in Kotlin.

Kotlin has to offer Android developers in this case. Java developers have much of these features as of JDK 8. One thing I noticed in particular was that you do not need to call stream() on collections in Kotlin. I don’t find this to be a huge surprise however. Much of the Java 8 functionality came in the form of the new Streams api, which they attached to the collection framework. Kotlin seems to have built such features directly into the collection classes.

You can click here to see Part 14

Kotlin Koans—Part 12

The last part of the Kotlin Koans tutorial had me use Object Expressions to sort an ArrayList. I observed that this could have been done with a lambda expression and I was correct.

This portion of the tutorial discusses implementing an interface with one abstract method. Kotlin calls such interfaces a SAM interface (Single Abstract Method). Whenever a developer is working with a SAM interface, they are free to use a lambda expression rather than an Object Expression.

Here is the Kotlin code that uses a lambda expression

fun task11(): List {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y.compareTo(x) })
    return arrayList
}

I should point out that Java 8 supports lambda expressions now also. Java calls SAM interfaces Functional interfaces. You can even add a @Functional annotation to such interfaces in Java.

I don’t see any huge advantage to Kotlin lambdas over Java ones at this point. Of course, Android developers may appreciate Kotlin’s lambda support.

You can view part 11 here.

Kotlin Koans—Part 1

I read that Android is going to officially support Kotlin now. Last year, I bought the IntelliJ IDE and one of the first things I noticed was that the IDE offered to make Kotlin classes. I had never done anything with Kotlin but I often wondered about it. It looked interesting to me, but now that Google has thrown in with Kotlin, I decided to give it try for myself.

This is the first in a series of posts where I’m going to work through the tutorials provided on kotlinlang.org. This first post was on the very first tutorial, which is the classical ‘Hello World’ style problem.

I started by cloning the github project that they give you. Here is what I got presented with.

package i_introduction._0_Hello_World

import util.TODO
import util.doc0

fun todoTask0(): Nothing = TODO(
    """
        Introduction.

        Kotlin Koans project consists of 42 small tasks for you to solve.
        Typically you'll have to replace the function invocation 'todoTaskN()', which throws an exception,
        with the correct code according to the problem.

        Using 'documentation =' below the task description you can open the related part of the online documentation.
            Press 'Ctrl+Q'(Windows) or 'F1'(Mac OS) on 'doc0()' to call the "Quick Documentation" action;
            "See also" section gives you a link.
            You can see the shortcut for the "Quick Documentation" action used in your IntelliJ IDEA
            by choosing "Help -> Find Action..." (in the top menu), and typing the action name ("Quick Documentation").
            The shortcut in use will be written next to the action name.

        Using 'references =' you can navigate to the code mentioned in the task description.

        Let's start! Make the function 'task0' return "OK".
    """,
    documentation = doc0(),
    references = { task0(); "OK" }
)

fun task0(): String {
    return todoTask0()
}

My job was to make the function task0 was to make it return “OK”. It wasn’t too painful. I just had to update task0

fun task0(): String {
    return "OK"
}

Once I did this, I ran the unit test that they give you to check if you did the task properly. This was easy to do in IntelliJ. The IDE provides you with a button to click on to run the test.
run_test
After I ran the test, I got the output the test was expecting.