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

Advertisements

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 14

I have always had a huge complaint about Java’s collection classes. The complaint involves switching between types of collections. For example, let’s suppose you have an ArrayList and you want to switch it to a set. Here is how you would do it in Java.

public class CollectionConvert {
    public static void main(String [] args){
        List lst = Arrays.asList(1, 2, 3);
        Set set = new HashSet(lst);
    }
}

Ok so let’s be honest here. It’s not as if it’s really that difficult to convert a List to a Set in Java. All of the constructors of the Java collection class accept another collection so we can pass an existing collection into a new collection to handle switching between collection types.

But let’s face the fact. It can be better than this. We are using two lines of code that could be done with one piece of code instead. Here is how it’s done in Kotlin.

fun Shop.getSetOfCustomers(): Set {
    // Return a set containing all the customers of this shop
    return customers.toSet()
}

Kotlin extends Java’s collection classes with these sort of conversion method. It may not seems like a big deal until you want to do something like this.

val lst = arrayListOf(1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9)

//Filter out duplicates and maintain a list
val noDuplicates = lst.toSet().toList()
//continue working with list instead of set...

The Set interface lacks method such as get(index). Sometimes it’s helpful to remove all duplicates in a list prior before working on the list. Java 8 does a lot of help with this problem, but I still think Kotlin is more consice.

List lst = Arrays.asList(1, 1, 1, 2, 2, 2, 3, 3, 3);
List noDuplicates = lst.stream().distinct().collect(Collectors.toList());

You can click here to see Part 13