Server Side Kotlin-03

Server Side Kotlin-03

·

7 min read

Table of contents

No heading

No headings in the article.

Kotlin uses the standard Java collection classes. Kotlin doesn’t have its own set of collection classes. All of your existing knowledge about Java collections still applies here. Java Class is Kotlin’s equivalent of Java’s getClass(). Let's create some collections.
val set = hashSetOf(1, 7, 53)
val list = arrayListOf(1, 7, 53)
val map = hashMapOf(1 to "one", 7 to "seven", 53 to "fifty-three")
Now print this
>>> println(set.javaClass)
>>> println(list.javaClass) >>> println(map.javaClass)
I will display following output

class java.util.HashSet

class java.util.ArrayList

class java.util.HashMap

Even though Kotlin’s collections are exactly the same classes as Java collections,you can do much more with them in Kotlin. For example, you can get the last element in a list or find a maximum in a collection of numbers:

>>> val strings = listOf("ab", "bc", "ca")

>>> println(strings.last())

>>> val numbers = setOf(0, 1, 2)

>>> println(numbers.max())

Kotlin strings are exactly the same things as Java strings. Kotlin hides the confusing method and provides as replacements several over-loaded extensions named split that have different arguments. The one that takes a regular expression requires a value of Regex type, not String . This ensures that it’s always clear whether a string passed to a method is interpreted as plain text or a regular expression. Here’s how you’d split the string with either a dot or a dash:

Creates a regular expression explicitly

Kotlin uses exactly the same regular expression syntax as in Java. The pattern here matches a dot (we escaped it to indicate that we mean a literal character, not a wild- card) or a dash. The API s for working with regular expressions are also similar to the standard Java library API s, but they’re more idiomatic. For instance, in Kotlin you use an extension function toRegex to convert a string into a regular expression But for such a simple case, you don’t need to use regular expressions. The other overload of the split extension function in Kotlin takes an arbitrary number of delimiters as plain-text strings:
>>>println("23.456-6.B".split(".", "-"))
\[23, 456, 6, B\]
Note that you can specify character arguments instead and write "12.345-6.A" .split('.', '-') , which will lead to the same result. This method replaces the similar Java method that can take only one character as a delimiter.

Multi line triple-quoted strings
The multi line string contains all the characters between the triple quotes, including indents used to format the code. A triple-quoted string can contain line breaks, but you can’t use special characters like \n . On the other hand, you don’t have to escape \ , so the Windows-style path "C:\Users\yole\kotlin-book" can be written as """C:\Users\yole kotlin-book""" . You can also use string templates in multi line strings. Because multi line strings don’t support escape sequences, you have to use an embedded expression if you need to use a literal dollar sign in the contents of your string. It looks like this: val price = """${'$'}99.9""" . One of the areas where multi line strings can be useful in your programs (besides games that use ASCII art) is tests. In tests, it’s fairly common to execute an operation that produces multi line text (for example, a web page fragment) and to compare the result with the expected output. Multi line strings give you a perfect solution for including the expected output as part of your test.

Essentials: filter and map The filter and map functions form the basis for manipulating collections. Many collection operations can be expressed with their help.

>>>val list = listOf(4,3,2,1)

> > > println(list.filter { it % 2 == 0 }) \[4, 2\]
The filter function goes through a collection and selects the elements for which the given lambda returns true : The result is a new collection that contains only the elements from the input collection that satisfy the predicate

The map function applies the given function to each element in the collection and collects the results into a new collection. You can transform a list of numbers into a list of their squares, for example: The result is a new collection that contains the same number of elements, but each element is transformed according to the given predicate (see figure 5.4).
>>>val list = listOf(4,3,2,1)

>>> println(list.map { it \* it })
\[16, 9, 4, 1\]

If you want to print just a list of names, not a list of people, you can transform the list using map
data class People(val name: String, val age: Int)

>>> val people = listOf(People("Ajay", 29), People("Vijay", 31))
>>> println(people.map { it.name }) \[Ajay, Vijay\]
Note that this example can be nicely rewritten using member references:

flatMap and flatten:

processing elements in nested collections The flatMap function does two things: At first it transforms (or maps) each element to a collection according to the function given as an argument, and then it combines (or flattens) several lists into one. An example with strings illustrates this concept well :

>>> val strings = listOf("pqr", "lmn")
>>>println(strings.flatMap { it.toList() })
\[p, q, r, l, m, n\]

The toList function on a string converts it into a list of applying the flatMap characters. If you used the map function together with function toList , you’d get a list of lists of characters, as shown in the second row in the figure. The flatMap function does the following step as well, and returns one list consisting of all the elements.

Suppose you have a storage of books, represented by the class Book : >>>class Book(val title: String, val authors: List)
Each book was written by one or more authors.
>>>val books = listOf(Book("C++", listOf("Balagurusamy")),

Book("Core Java", listOf("Herbert Shield")),

Book("Advance Java", listOf("Herbert Shield",

"Dietel")))

>>>println(books.flatMap { it.authors }.toSet())
\[Balagurusamy, Herbert Shield, Dietel\]

Each book can be written by multiple authors, and the book.authors property stores the collection of authors. The flatMap function combines the authors of all the books in a single, flat list. The toSet call removes duplicates from the resulting collection—so, in this example, Herbert Shield is listed only once in the output. You may think of flatMap when you’re stuck with a collection of collections of elements that have to be combined into one. Note that if you don’t need to transform anything and just need to flatten such a collection, you can use the flatten function: listOfLists.flatten() .

If you want to keep only people older than 30, you can use filter :The filter function can remove unwanted elements from a collection, but it doesn’t change the elements. Transforming elements is where map comes into play.

>>> val people = listOf(People("Ajay", 29), People("Vijay", 31)) >>>println(people.filter { it.age > 30 }) \[People(name=Vijay, age=31)\]

>>> [people.map](People::name)
res31: kotlin.collections.List<kotlin.String> = [Ajay, Vijay]

You can easily chain several calls like that. For example, let’s print the names of people older than 30:

>>> people.filter { it.age &gt; 30 }.map(People::name)
res34: kotlin.collections.List&lt;kotlin.String&gt; = \[Vijay\]

Now, let’s say you need the names of the oldest people in the group. You can find the maximum age of the people in the group and return everyone who is that age. It’s easy to write such code using lambdas:

>>> people.filter { it.age == people.maxBy(People::age).age }
But note that this code repeats the process of finding the maximum age for every person, so if there are 100 people in the collection, the search for the maximum age will be performed 100 times! The following solution improves on that and calculates the maximum age only once:
>>>val maxAge = people.maxBy(People::age).age people.filter { it.age == maxAge }

Don’t repeat a calculation if you don’t need to! You can also apply the filter and transformation functions to maps:

>>> val numbers = mapOf(10 to "ten", 100 to "hundred") >>>println(numbers.mapValues { it.value.toUpperCase() }) {10=TEN, 100=HUNDRED}

There are separate functions to handle keys and values. filterKeys and mapKeys filter and transform the keys of a map, respectively, where as filterValues and mapValues filter and transform the corresponding values.

groupBy: converting a list to a map of groups
Imagine that you need to divide all elements into different groups according to some quality. For example, you want to group people of the same age. It’s convenient to pass this quality directly as a parameter. The groupBy function can do this for you:

>>> val people = listOf(People("Ajay", 31), ... People("Vijay", 29), People("Shyam", 31))
println(people.groupBy { it.age })
{31=\[People(name=Ajay, age=31), People(name=Shyam, age=31)\], 29=\[People(name=Vijay, age=29)\]}
The result of this operation is a map from the key by which the elements are grouped ( age , in this case) to the groups of elements (persons); Each group is stored in a list, so the result type is Map<Int, List> . You can do further modifications with this map, using functions such as mapKeys and mapValues .

As another example, let’s see how to group strings by their first character using member references:

>>> val list = listOf("c", "cd", "d")
>>>println(list.groupBy(String::first))
{c=\[c, cd\], d=\[d\]}

Note that first here isn’t a member of the String class, it’s an extension. Nevertheless, you can access it as a member reference.
(public beta 1.0 )