Why would a Scala buffer iterator range - sometimes?

In Scala 2.9.1, this works great:

scala> (1 to Int.MaxValue).sum res6: Int = -1073741824 

However, this ends with a heap:

 scala> (1 to Int.MaxValue).toIterator.sum java.lang.OutOfMemoryError: GC overhead limit exceeded 

But it works insanely:

 scala> (1 to Int.MaxValue).iterator.sum res8: Int = -1073741824 

Why can each of them be different?

+4
source share
2 answers

toIterator defined in TraversableLike as

 def toIterator: Iterator[A] = toStream.iterator 

therefore, it creates a Stream in the background, which stores all the elements in memory during the iteration.

( Edit ): I think the stream structure is not really a problem. However, toStream itself calls toBuffer , which in turn copies each value.)

iterator , on the other hand, is defined in IndexedSeqLike , which uses a specialized structure that does not contain any elements in memory.

+7
source

If you look at the code in more detail, then how everything will be determined.

When you call toIterator, it takes everything in sequence and copies it to an ArrayBuffer (first it tries to convert it to a stream.) This copy probably ended up out of memory.

When you use an iterator, it creates an instance of the protected Elements class that returns a BufferedIterator. This uses the class itself to return elements.

 protected class Elements(...) ... { ... def next: A = { if (index >= end) Iterator.empty.next val x = self(index) index += 1 x } } 
+2
source

Source: https://habr.com/ru/post/1382724/


All Articles