Do not compute the size of a collection to check for emptiness

When checking whether a collection is empty, use isEmpty or nonEmpty rather than the all too common size == 0.

Reasons

It’s inefficient

Collections such as List require a complete traversal to compute their size. Doing so just to check whether there’s at least one element is clearly more expensive than it needs to be.

To prove this point, let’s create a simple benchmarking method:

def time[A](t: => A): Long = {
  val now = System.currentTimeMillis()
  t
  System.currentTimeMillis() - now
}

We’ll also need an unreasonably large List:

val list = (0 to 10000000).toList

We can now check that one approach is indeed far longer than the other:

time(list.isEmpty)
// res0: Long = 0L

time(list.size == 0)
// res1: Long = 41L

It’s unsafe

Some collections are infinite, and will loop forever when you try to compute their length:

// Don't run this.
Stream.from(1).size

isEmpty, on the other hand, behaves sanely:

Stream.from(1).isEmpty
// res2: Boolean = false

Checked by

LinterRule
Scapegoat
  • AvoidSizeEqualsZero
  • AvoidSizeNotEqualsZero