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.

6 Responses

  1. Love it. Knew about some of these, and just found out about others (partition, takeWhile), etc.

    I didn’t care about this stuff when I first started using Scala because I mostly used it as Java with anonymous functions. Now though, I’m really appreciating the thought that went into the libraries.

    Blog’s like this are what will help the skeptics out there give scala a try, keep up the good work.

    • Thanks Vincent!
      I like this functions because they can save you a lot of lines of boring and repetitive code.

      I’m happy you liked my blog!

  2. Recuérdame por qué seguimos usando java…

    • Creo que en el momento en que algún proyecto grande y serio empiece a utilizar los “nuevos” lenguajes de la JVM, muchísima gente empezará a usarlos en sus proyectos.

  3. Glück, mein Freund!

Leave a comment