Kotlin Collections – Useful Functions

Useful functions for Kotlin Collections.

fun main() {
    val setInts = setOf(10, 15, 19, 5, 3, -22)

    println(setInts.filter { it % 2 != 0 }) // Odd numbers only

    val immutableMap = mapOf(1 to Car3("green", "Toyota", 2015),
        2 to Car3("red", "Ford", 2016),
        3 to Car3("silver", "Honda", 2013),
        17 to Car3("red", "BMW", 2015),
        8 to Car3("green", "Ford", 2010)
    )

    println("2016 cars only: ${immutableMap.filter { it.value.year == 2016 }}") // 2016 cars only

    val mutableMap = mutableMapOf(1 to Car3("green", "Toyota", 2015), 2 to Car3("red", "Ford", 2016), 3 to Car3("silver", "Honda", 2013))

    mutableMap.filter { it.value.colour == "silver" }

    println(mutableMap) // Map hasn't changed by being filtered. Filter creates new instance of the map.

    // Add 10 to every element and create new
    val ints = arrayOf(1, 2, 3, 4, 5)
    val add10List: MutableList<Int> = mutableListOf()
    for (i in ints) {
        add10List.add(i + 10)
    }
    println("Add10List: ${add10List}")
    // The Kotlin way - using the map FUNCTION (not Collection)
    val add10List2 = ints.map { it + 10 }
    println("Add10List2: ${add10List2}")

    // Create a List that contains all the years of the Cars in our Map
    val carYearsList = immutableMap.map { it.value.year }
    println("Car years list: ${carYearsList}")

    // You can chain filter and map functions together:

    println("Ford cars only: ${immutableMap.filter { it.value.model == "Ford" }}") // Ford cars only

    println("Ford car colours: ${immutableMap.filter { it.value.model == "Ford" }.map { it.value.colour}}") // Ford car colours

    // If all the elements in a Collection match a condition:
    println(immutableMap.all { it.value.year > 2014 }) // Are all cars modern (post-2015)?
    println(immutableMap.any { it.value.year > 2014 }) // Are any cars modern (post-2015)?
    println(immutableMap.count { it.value.year > 2014 }) // How many cars are modern (post-2015)?
    // To find value that matches we can move them into a List and use the find function
    val cars = immutableMap.values
    println("First modern car: ${cars.find { it.year > 2014}}") // Finds first item in List that satisfies condition

    println("Cars grouped by colour: ${cars.groupBy { it.colour }}") // Group cars by colour
    println("Cars sorted by year: ${cars.sortedBy { it.year }}") // Sorted by year

    println("Sorted by key: ${immutableMap.toSortedMap()}") // Sorted by key

}

data class Car3(val colour: String, val model: String, val year: Int)

 

Kotlin Arrays

Kotlin’s handling of arrays

fun main() {
    val names = arrayOf("John", "Jane", "Jill", "Joe") // Assumes Strings

    val longs1 = arrayOf(1L, 2L, 3L) // State Long by use of L
    val longs2 = arrayOf<Long>(1, 2, 3, 4) // Or by declaring datatype in arrayOf<>
    val longs3 = arrayOf(1, 2, 3, 4) // Otherwise will assume Ints

    println(longs2 is Array<Long>)
//    println(longs3 is Array<Long>) // Will fail because is Int
    println(longs3 is Array<Int>)

    println(longs1[2])

    val evenNumbers = Array(16) {i -> i*2} // Use lambda expression to get even numbers up to 30
    for (number in evenNumbers) {
        println(number)
    }

    val lotsOfNumbers = Array(100001) {i -> i} // Numbers from 0 to 100,000
    val allZeroes = Array(100) {0} // One hundred zeroes

    var someArray: Array<Int> // If you don't want to initialise it till later
    someArray = arrayOf(1, 2, 3, 4)
    for (number in someArray) {
        println(number)
    }

    someArray = Array(6) {i -> (i + 1) * 10}
    for (number in someArray) {
        println(number)
    }

    val mixedArray = arrayOf("hello", 22, BigDecimal(10.5), 'a') // Can have array of mixed datatypes i.e. Any
    for (element in mixedArray) {
        println(element)
    }

    val myIntArray = arrayOf(3, 99, 234, 54)
//    DummyClass().printNumbers(myIntArray) // Fails because it expects IntArray but found Array<Int>
    val myIntArray2 = intArrayOf(3, 99, 45, 756) // Use specific Array types
    DummyClass().printNumbers(myIntArray2) // Works!

//    var someOtherArray = Array<Int>(5) // Fails. By declaring the size (5) we are actually trying to instantiate the array, so we would need to add values
    var someOtherArray: Array<Int> // This is okay
    var anotherArray = IntArray(5) // However, primitive type arrays allow this as they're initialised to default, in this case all zeroes
    DummyClass().printNumbers(anotherArray)

    // So can you instantiate an array of fixed size? An array of nulls. Potentially risky as could lead to NullPointerExceptions, so you have to explicitly ask for them.
    // Not a problem with primitive arrays as they are initialised with defaults e.g. zeroes for IntArray
    // However, array of Objects is potentially null, so we use ArrayOfNulls to warn compiler
    val nullableInts = arrayOfNulls<Int>(5)
    for (i in nullableInts) {
        println(i)
    }
    // Try nullableInts[0]. and see how few options are available
    nullableInts[3] = 5
    val intValue = nullableInts[3]?.rem(2) // Now options are available provided you use ?


    // If you want pass an Array<Int> to Java you can convert it:
    DummyClass().printNumbers(evenNumbers.toIntArray()) // evenNumbers was an Array<Int>
    // And vice versa
    val convertedIntArray = myIntArray2.toTypedArray() // Converts a primitive IntArray to Array<Int>
}
public class DummyClass {

    public String isVacationTime (boolean onVacation) {
        return onVacation ? "I'm on vacation" : "I'm working";
    }

    public void printNumbers (int[] numbers) {
        for (int number: numbers) {
            System.out.println(number);
        }
    }
}