Daniel
Daniel

Reputation: 6039

`zipWithIndex` or not: how much do we gain?

Suppose I have a case class for a certain purpose.

case class SamplePair(
  arrayOfNumbers: ArrayBuffer[Int]
)

Suppose I have sequenceOfSamplePair have a Seq of our basic SamplePair, and I want to add some ordered numbers to the arrayOfNumbers element of each element.

One way is doing this:

val ctr = new AtomicInteger(0)
sequenceOfSamplePair.foreach{ entry => 
   entry.arrayOfNumbers += ctr.getAndIncrement()
}

Another way is doing this, using zipWithIndex.

sequenceOfSamplePair.zipWithIndex.foreach {
      case (entry, ctr) =>
        entry.arrayOfNumbers += ctr
 }

What would be the reasons to prefer the implementation using zipWithIndex? Is it more "functional"?

Upvotes: 1

Views: 523

Answers (2)

bjfletcher
bjfletcher

Reputation: 11508

I've just done some profiling with these two methods. There's no clear winner. If the pattern matching in the zipWithIndex is replaced with direct references (_1 and _2) then it's slightly faster but still not a clear winner.

If you however use streaming like the following:

Stream.range(0, sequenceOfSamplePair.length).map { i =>
  sequenceOfSamplePair(i) += i
}

then, it's about 6x faster. That's because it is really very simple, just go through the counter one by one, directly adding to the number. 6x is a lot faster, meaning it seems that getAndIncrement makes it very, very slow in relative terms.

Upvotes: 2

Andreas Neumann
Andreas Neumann

Reputation: 10884

As both of your approaches are not functional i'd go with the first implementation. In the second approach you mix a functional construct with a imperative construct whereas you loose all gains you could get out of a functional solution.

Also using a mutable buffer in the case class goes not well with a mutable Buffer.

a more functional approach could look like

case class SamplePair(numbers: List[Int])

val extendedSequenceOfSamplePair = sequenceOfSamplePair.zipWithIndex.map {
  case ( sp@SamplePair(oldNumbers), idx) => sp.copy( numbers = idx :: oldNumbers)
}

Upvotes: 2

Related Questions