When you want a set number of items from the beginning of a stream, you use Stream.take
. When you don’t care so much about the number, but rather the nature of the items, use Stream.takeWhile
.
Stream.takeWhile
starts at the beginning of the stream and applies a predicate to each item, one by one. It returns each item in a new stream until it reaches an item that does not meet the predicate:
Note that Stream.takeWhile
does not return the item that fails to meet the predicate. It stops with the last item that meets the predicate.
Perhaps you have a sensor feeding you temperature readings once per minute:
import java.time.{LocalDateTime, Month} case class Reading( temperature: Double, timestamp: LocalDateTime) val readings = Stream( Reading(89.5, LocalDateTime.of(2015, Month.JULY, 19, 10, 0)), Reading(90.1, LocalDateTime.of(2015, Month.JULY, 19, 10, 1)), Reading(89.9, LocalDateTime.of(2015, Month.JULY, 19, 10, 2)), Reading(90.0, LocalDateTime.of(2015, Month.JULY, 19, 10, 3)), Reading(90.1, LocalDateTime.of(2015, Month.JULY, 19, 10, 4)), Reading(-1000.0, LocalDateTime.of(2015, Month.JULY, 19, 10, 5)), Reading(-1000.0, LocalDateTime.of(2015, Month.JULY, 19, 10, 6)), Reading(90.2, LocalDateTime.of(2015, Month.JULY, 19, 10, 7)) )
Now to get all readings up until the thermometer returns the data-not-valid indicator, employ Stream.takeWhile
:
val valid = readings takeWhile { _.temperature != -1000.0 } // valid: scala.collection.immutable.Stream[Reading] = // Stream( // Reading(89.5,2015-07-19T10:00), // Reading(90.1,2015-07-19T10:01), // Reading(89.9,2015-07-19T10:02), // Reading(90.0,2015-07-19T10:03), // Reading(90.1,2015-07-19T10:04) // )
Finally, Stream.takeWhile
doesn’t balk if it never reaches an element that fails to meet the predicate:
val all = Stream(1,3,4,7) takeWhile { _ < 10 } // all: scala.collection.immutable.Stream[Int] = // Stream(1, 3, 4, 7)
As with Stream.take
, the other collection types also define takeWhile
:
One reply on “Scala Saturday – The Stream.takeWhile Method”
[…] you have the same temperature sensor as the one in my post on Stream.takeWhile. This time, instead of once per minute, assume that it feeds you temperature readings once per […]