Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: May 20, 2024
Scala is renowned for its robust collections standard library, which offers many effective methods for manipulating and performing actions on collections.
In this tutorial, we’ll explore two such methods, filter() and takeWhile(). Both are useful for selecting elements from a collection based on specific criteria. However, they operate differently.
The filter() function iterates through every element in a collection and applies the given predicate. It returns a new collection containing only the elements where the predicate evaluates to true. Let’s look at a simple example to understand its functionality:
val numbers = List(1, 2, 3, 4, 5, 6)
val oddNumbers = numbers.filter(_ % 2 != 0)
oddNumbers shouldBe List(1, 3, 5)
In the above code, we use the filter() method on a List to extract only the odd numbers.
Here, we used a finite collection for the filtering operation. Now, let’s look at what happens if we apply the filter() method to an infinite or unbounded collection. We can use a LazyList to create an infinite collection. Let’s look at an example:
val infiniteNumbers = LazyList.from(1)
infiniteNumbers.filter(_ < 100).toList // will not terminate
In this scenario, we create an infinite collection of natural numbers using the LazyList.from() method. Subsequently, we can apply the filter() method to this infiniteNumbers variable. However, due to the nature of an infinite sequence, the filter() operation continues iterating through the elements endlessly. Consequently, the toList() method called on the filtered lazy list never completes.
The takeWhile() method also applies the given predicate on the collection. However, it traverses the collection sequentially, stopping when the predicate function evaluates to false for the first time. Let’s look at a simple example:
val numbers = List(1, 2, 3, 4, 5, 6)
val numbersBeforeFirstEven = numbers.takeWhile(_ % 2 != 0)
numbersBeforeFirstEven shouldBe List(1)
The above example is similar to the code we used for the filter() method to get odd numbers. However, instead of the filter() method, we use takeWhile(). The takeWhile() applies the predicate and returns the elements until the condition is no longer satisfied for the first time, thereby returning a list containing only element 1.
Let’s try with another sample list to observe the behavior of takeWhile():
val numbers = List(1, 3, 4, 5, 6)
val numbersBeforeFirstEven = numbers.takeWhile(_ % 2 != 0)
numbersBeforeFirstEven shouldBe List(1, 3)
Here, the takeWhile() returned List(1, 3) because the predicate failed only for the third element in the list, which is the number 4.
Now, let’s look at what happens if we apply the takeWhile() function to an infinite list:
val infiniteNumbers = LazyList.from(1)
val first100 = infiniteNumbers.takeWhile(_ < 100).toList
first100 shouldBe (1 to 99).toList
In this scenario, the test passes because the takeWhile() terminates execution immediately once the predicate fails, effectively avoiding any potential for infinite processing.
It’s important to understand that element ordering influences the outcomes of the takeWhile() operation, unlike the filter() method, which remains unaffected by the order of elements.
Below is a table summarizing the main differences between the filter() and the takeWhile() methods for quick reference:
| Behavior | filter() | takeWhile() |
|---|---|---|
| Operation | Selects elements based on condition | Selects elements until a condition is false |
| Iteration | Iterates over all elements of the collection | Iterates only until the first failure of the predicate |
| Impact of Element Order | No Impact | Impacted |
| Termination | No Early Termination | Early Termination |
| Practical Usecase Example | Filtering data based on different fields | Analyzing time-series data to determine when a threshold is exceeded in temperature readings |
In this article, we explored the differences between filter() and takeWhile() methods on the collection. While both methods offer powerful ways to select elements from collections based on specific criteria, they differ in their behaviors and performance characteristics. The filter() method is ideal for selectively retaining elements that satisfy a condition, whereas the takeWhile() method excels at extracting elements until a condition becomes false for the first time.
By effectively using these methods, we can write cleaner, more concise code and improve the performance of our Scala applications.