I'm curious if Scala has some gem hidden in its collection classes that I can use. Basically I'm looking for something like a FIFO queue, but that has an upper-limit on its size such that when the limit is hit, the oldest (first) element is removed from the queue. I've implemented this myself in Java in the past, but I'd rather use something standard if possible.
4 Answers
An often preferable alternative to subclassing is the (unfortunately named) "pimp my library" pattern. You can use it to add an enqueueFinite
method to Queue
, like so:
import scala.collection.immutable.Queue
class FiniteQueue[A](q: Queue[A]) {
def enqueueFinite[B >: A](elem: B, maxSize: Int): Queue[B] = {
var ret = q.enqueue(elem)
while (ret.size > maxSize) { ret = ret.dequeue._2 }
ret
}
}
implicit def queue2finitequeue[A](q: Queue[A]) = new FiniteQueue[A](q)
Whenever queue2finitequeue
is in scope, you can treat Queue
objects as though they have the enqueueFinite
method:
val maxSize = 3
val q1 = Queue(1, 2, 3)
val q2 = q1.enqueueFinite(5, maxSize)
val q3 = q2.map(_+1)
val q4 = q3.enqueueFinite(7, maxSize)
The advantage of this approach over subclassing is that enqueueFinite
is available to all Queue
s, including those that are constructed via operations like enqueue
, map
, ++
, etc.
Update: As Dylan says in the comments, enqueueFinite
needs also to take a parameter for the maximum queue size, and drop elements as necessary. I updated the code.

- 21,002
- 4
- 67
- 80
-
Cool. But how do you pass the maximum queue size ? – paradigmatic Aug 03 '11 at 07:10
-
I see two options: your finite queue is mutable, in which case you change the size after its creation (removing elements if necessary), or your queue is immutable, in which case you would add the limit to the `enqueueFinite` method. – Dylan Aug 03 '11 at 14:00
-
or you could add an implicit `Int` parameter. – Jus12 Sep 19 '14 at 19:24
-
1Why not use an implicit class? `object FiniteQueue { implicit class FiniteQueue[A](q: Queue[A]) { def enqueueFinite[B >: A](elem: B, maxSize: Int): Queue[B] = { var ret = q.enqueue(elem) while (ret.size > maxSize) { ret = ret.dequeue._2 } ret } } }` – AlonL Oct 18 '14 at 21:13
-
for implicit with mutable: `object FiniteQueue { implicit class FiniteQueue[A](q: mutable.Queue[A]) { def enqueueFinite(elem: A, maxSize: Int): Unit = { q.enqueue(elem) while (q.size > maxSize) { q.dequeue() } } } }` – Varon Jul 23 '17 at 15:00
-
really nice approach, thx.I would change `class` to `case class` and rename `q` to `queue` then the suborindated queue is accessible easily, too, e.g. for getting its `size` – Hartmut Pfarr Dec 27 '21 at 11:24
Why don't you just subclass a FIFO queue? Something like this should work: (pseudocode follows...)
class Limited(limit:Int) extends FIFO {
override def enqueue() = {
if (size >= limit) {
//remove oldest element
}
super.enqueue()
}
}

- 41,826
- 12
- 125
- 142
-
1Another option is to use the "pimp my library" pattern to add an `enqueueFinite` method to the Queue class. This seems preferable because it avoids type problems with the usual methods (`map`, `++`, ...) – Kipton Barros Aug 02 '11 at 23:47
-
@Kipton you should make your own answer. I think it's really preferable indeed. – Daniel C. Sobral Aug 02 '11 at 23:57
-
Does anyone have the actual code for the pseudo code above? New to scala so struggling with this a little? – IncompleteCoder Aug 10 '17 at 15:52
Here is an immutable solution:
class FixedSizeFifo[T](val limit: Int)
( private val out: List[T], private val in: List[T] )
extends Traversable[T] {
override def size = in.size + out.size
def :+( t: T ) = {
val (nextOut,nextIn) = if (size == limit) {
if( out.nonEmpty) {
( out.tail, t::in )
} else {
( in.reverse.tail, List(t) )
}
} else ( out, t::in )
new FixedSizeFifo( limit )( nextOut, nextIn )
}
private lazy val deq = {
if( out.isEmpty ) {
val revIn = in.reverse
( revIn.head, new FixedSizeFifo( limit )( revIn.tail, List() ) )
} else {
( out.head, new FixedSizeFifo( limit )( out.tail, in ) )
}
}
override lazy val head = deq._1
override lazy val tail = deq._2
def foreach[U]( f: T => U ) = ( out ::: in.reverse ) foreach f
}
object FixedSizeFifo {
def apply[T]( limit: Int ) = new FixedSizeFifo[T]( limit )(List(),List())
}
An example:
val fifo = FixedSizeFifo[Int](3) :+ 1 :+ 2 :+ 3 :+ 4 :+ 5 :+ 6
println( fifo ) //prints: FixedSizeFifo(4, 5, 6)
println( fifo.head ) //prints: 4
println( fifo.tail :+ 7 :+8 ) //prints: FixedSizeFifo(6, 7, 8)

- 40,153
- 18
- 88
- 147
This is the approach I toke with extending Scala's standard mutable.Queue class.
class LimitedQueue[A](maxSize: Int) extends mutable.Queue[A] {
override def +=(elem: A): this.type = {
if (length >= maxSize) dequeue()
appendElem(elem);
this
}
}
And simple use-case
var q2 = new LimitedQueue[Int](2)
q2 += 1
q2 += 2
q2 += 3
q2 += 4
q2 += 5
q2.foreach { n =>
println(n)
}
You'll get only 4
and 5
in the console as the old elements were dequeued beforehand.

- 4,113
- 1
- 26
- 33