Welcome back. In the earlier video, I talked about the basic idea behind Higher Order Control
abstraction. In this video,
I will talk about the four fundamental control abstractions that Scala implements for almost
every
collection type.
Here is the list of those abstractions.
- foreach
- map
- flatMap
- filter and withFilter
All these methods are same in one respect. They take a function as an argument and apply the
function to each element in
the collection. So, all of them are a kind of specialized loop constructs.
But they are not same. Each one serves a different purpose. Let's try to understand the
specifics
of these methods using a List collection.
Scala foreach
The foreach is the simplest one. It takes one function as an argument and applies the function
to each element of the collection.
That's why it has got the name as foreach.
It's purely a loop. But the most important feature is that it doesn't return anything. The
return
type of the foreach method is a Unit. Here is a primary example.
I have a list, and I have a function f1. I call the foreach on the list and pass the function
f1. It returns nothing. My
function f1 does return a value, but foreach is designed to discard that value.
While working with Scala collections, we use the foreach for a side effect. I mean, if you
have
a function that has a side effect and you want to apply it to all elements of a collection, use
the
foreach method. The most common example is the println.
Scala map
The next one is the map method. The map method is the most commonly used method. Like foreach,
this one is also a loop. It
takes a function and applies the function to each element. But unlike foreach, the map method
returns
a value.
Let's apply the function f1 on each element of my list.
What do you see? It executes the function f1 for each element of the list, and hence we get
those outputs. But it also returns
a list of strings. So, the map method takes a function and applies it to all elements, collects
the
result of the function and returns a new collection. So, the return type of the map method is a
collection
of the return type of f1.
The most common use of the map method is to transform a collection into a new collection by
applying
some transformation logic to each element of the existing collection.
Scala flatMap
The next one is the flatMap. The flat map is a specialized version of the map method. You can't understand it without an example. So, let's take an example.
We have a function there. It takes a string and breaks it into words. The return type of the function f3 is an array of strings. Let's make a list of two strings.
Now, we will apply the map method on this list.
What do you see? A List of an array. That is what I expected because map method returns a
collection of the return type of
f3. The return type of f3 is an array, so we get a List of an Array.
Now, let's try the flat map.
Do you see the difference? The
flatMap goes one step further. It takes the return value of f3 and breaks them once
again.
So ultimately you get a flattened list. The flat map method has flattened the array into
strings.
So, if you are using map method and getting a collection of an array but you wanted a flat
output,
I mean break the array further into elements, use the flat map instead of map method.
You must be careful while using the flat map because, if the output of f3 is not a
collection,
you may get unexpected results.
Scala filter and withFilter
The final item is the filter. The filter method is simple. Like other methods that we just discussed, the filter takes a Boolean function, applies it to all elements and returns only those elements that qualify the Boolean condition. Here is a very basic example.
The most common use of the filter method is to filter out some elements from an existing
collection and create a new collection.
The
withFilter is also same as the filter. There is a small difference.
The filter method returns a new collection, but
withFilter doesn't return you a new collection. It will apply the Boolean function
just
before the subsequent method calls. Let me show you an example.
In this example, the Boolean function applies to each element just before it applies the map
method to that specific element.
If the Boolean function returns true, then the element goes to the map method otherwise Scala
will
filter that out and it doesn't go to the map method.
In fact, if you apply filter method instead of
withFilter, you should get the same results. But
withFilter
is efficient because it's a lazy method and applies the Boolean function when we use the
element for the subsequent call.
Great! We will talk about the for expression in the next video.