The power of Lists in Scala

Let me introduce you the piece of code possibly most used in history:

for(int i = 0; i < list1.length() ; i++){ //do something }

Since java 1.5 we have a more concise way to do the same, the foreach iteration:

for(Object o : list1){ //do something }

If we want to create a list with all elements of list1 that fulfill some condition, we need some boilerplate code:

List list2 = new ArrayList(); for(Integer i : list1){ if(i > 0){ list2.add(i); } }

Every time we want to find elements that fulfill some condition, we need to copy this code except for the third line, which has to be adapted.

One of the main goals of Scala is to reduce the boilerplate code that exists in our Java code. To accomplish this goal, there are some higher-order operators, which can take a function as a parameter. Some useful higher-order operators will be described in this post.

Filter

The filter operator takes as operands a list of type List[T] and one function of type T => Boolean called predicate. This operator returns a new list with all elements of the original list for which the predicate is true. With this operator we can, in only one line, do the same that the Java code.

scala> val list1 = List(1,3,4,0,-1,6)
list1: List[Int] = List(1, 3, 4, 0, -1, 6)
scala> val list2 = list1 filter (_ > 0)
res0: List[Int] = List(1, 3, 4, 6)

The list created will contain only the elements of list1 that are greater than 0.

Find

This operator is very similar to filter, except that returns the first element for which the predicate is true. Actually it returns an optional value; this is the Scala approach for nullable objects. If at least one element makes predicate true, it will return Some(T), otherwise None. This approach ensures in compilation time that no optional values are considered as common variables of type T.

scala> list1 find (_ > 0)
res1: Option[Int] = Some(1)
scala> list1 find (_ > 100)
res2: Option[Int] = None

Partition

The partition operator returns a pair of lists. The first one includes all elements that satisfies the predicate. The second includes all elements for which the predicate is false.

scala> list1 partition (_ > 0)
res3: (List[Int], List[Int]) = (List(1, 3, 4, 6),List(0, -1))

TakeWhile

The takeWhile operator iterates the original list until it finds one element that doesn’t satisfy the predicate, all this elements are added in the result list. In other words, it returns the longest prefix such that every element satisfies the predicate.

scala> list1 takeWhile (_ > 0)
res4: List[Int] = List(1, 3, 4)

DropWhile

The dropWhile operator iterates the original list until it finds one element that doesn’t satisfy the predicate, the remaining elements are added in the result list. In other words, it drops the longest prefix such that every element satisfies the predicate.

scala> list1 dropWhile (_ > 0)
res5: List[Int] = List(0, -1, 6)

These are few operations that can help us in our everyday coding. The less lines we code, the less chances of introducing errors we have. In addition, we can avoid repeating the most repetitive and error-prone code.

Advertisements

Scala: Arrays, Lists, Sets and Maps

Despite all Scala code is translated to Java code, there are some differences between Scala Collections and Java Collections. In this post we will try to explain four types of collections: Arrays, Lists, Sets and Maps.

Arrays

In Scala, in contrast to Java, there is an Array object and it can be created in the same way as Java does. However, the syntax differs. The first one is the classical way to create an object.

var classicWay = new Array[String](3)
classicWay(0) = “The”
classicWay(1) = “classic”
classicWay(2) = “way”

There are two important differences to notice. The way to specify the type of the Array is [] instead of <>. The other one is the way to instance the array, in Scala we use the () instead of []. There is also another way to create and initialize an Array, which is less verbose and more compact.

var compactWay = Array(“I”,”like”,”this”,”way”)

As it can be seen, there is no need to specify the type of the Array, the compiler will infer that the type is String. Here there is another difference, we use the companion class to get an instance of Array. Companion classes will be explained in another post, but they can be seen as static classes or utility classes.
Obviously, we can’t access a position of the Array with the [] operator, instead, the () operator is used. For instance:

print(compactWay(1))
compactWay(0) = “We”

It will be transformed into:

print(compactWay.apply(1))
compactWay.update(0,”We”)

Lists

Lists in Scala are always immutable (in Java they can be mutable), they are designed to enable a functional style programming. That means that, once created, a Scala List can’t be modified. But there are operators on Lists, so maybe you would be wondering why there are operators on Lists if they are immutable objects. As in Strings, when you invoke any operation on a List, another List is created and returned when an operator is applied. Maybe, the two main operators are ::: and :: . The first one is the operator for list concatenation. The second one is the operator to prepend an element to a List. Yes, you read it well: prepend (in Scala you can’t append elements to a list). This is because prepend an element at the beginning of a list is a constant-time operation, whereas append is a linear-time operation. Usually, the owner of an operation is the left operand, but in :: the owner is the right operand. Here there are some examples.

val list1 = List(“This”,”is”)
val list2 = List(“a”,”list”)
val list3 = list1 ::: list2
val list4 = “Hey!” :: list3
println(list1)
println(list2)
println(list3)
println(list4)

List1 and list2 remain immutable, they didn’t change. List3 is a new list resulting of concatenating list1 and list2. In list4, the String “Hey!” is prepended to list3. The complete api of List object can be found here.

Sets

There are two kinds of Sets, the immutable and the mutable one. The difference between mutable and immutable objects is that when an object is immutable, the object itself can’t be changed. The most known immutable object in Java is String: once you have created a String, it remains the same until it is destroyed.

By default, Scala uses the immutable Set. If you want to use the mutable Set, you’ll have to import the class. The hierarchy of the Set is the following:

Hierarchy for the Scala Set object

It’s not a problem to change between mutable and immutable collections, since all of them share the same contract. In most cases, no change will be necessary.

You can create a Set in the same way you create a List. The most useful operations are + and +=, but the second one it’s only available in mutable Sets. In the immutable Sets  mySet += “foo”  is transformed to mySet = mySet.+(“foo”). Here there is a simple example of immutable sets:

var trilogies = Set(“The Godfather”, “Lord of the Rings”)
trilogies += “Millennium”
println(trilogies)

In this example, a new Set is created in line 2. If we import the mutable Set, in this same line, the trilogies set will be modified:

import scala.collection.mutable.Set
var trilogies = Set(“The Godfather”, “Lord of the Rings”)
trilogies += “Millennium”
println(trilogies)

Maps

As in Sets, there are two kinds of Maps, the immutable and the mutable ones. The hierarchy of Map is analog to Map’s hierarchy:
Hierarchy of Scala Set
There are two ways to create a Map in Scala, one of them can only be used with the mutable Maps:

import scala.collection.mutable.Map
var steps = Map[Int, String]()
steps += (1 -> “Go straight on”)
steps += (2 -> “Take the second turn on the left”)
steps += (3 -> “It’s opposite the hairdresser”)
println(steps(3))

Obviously, this Map needs to be mutable, because it has been modified since its creation. Ok, we know how to create mutable Maps, but how immutable Maps can be created?

var steps = Map (1 -> “Go straight on”, 2 -> “Take the second turn on the left”, 3 -> “It’s opposite the hairdresser”)
print(steps(3))

Here again, there is no need to specify the type of the Array, the compiler will infer that the type is Int for the keys and String for the values. The operator -> is useful for creating Tuples. A Tuple can be seen as an array of objects, but they don’t need to share the same type.