scala队列的最大长度

时间:2011-08-02 21:17:01

标签: scala scala-collections

我很好奇Scala是否在我可以使用的集合类中隐藏了一些gem。基本上我正在寻找类似FIFO队列的东西,但是它的大小有一个上限,这样当命中限制时,最旧的(第一个)元素将从队列中删除。我过去曾用Java自己实现过,但如果可能的话,我宁愿使用标准的东西。

4 个答案:

答案 0 :(得分:19)

子类化的一个常用的替代方法是(不幸命名的)“pimp my library”模式。您可以使用它将enqueueFinite方法添加到Queue,如下所示:

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)

只要queue2finitequeue在范围内,您就可以将Queue个对象视为拥有enqueueFinite方法:

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)

此方法优于子类化的优势在于enqueueFinite可用于所有Queue,包括通过enqueuemap,{{等操作构建的++ 1}}等等。

更新:正如Dylan在评论中所说,enqueueFinite还需要获取最大队列大小的参数,并根据需要删除元素。我更新了代码。

答案 1 :(得分:4)

为什么不直接对FIFO队列进行子类化?这样的东西应该有效:(伪代码跟着......)

class Limited(limit:Int) extends FIFO {
  override def enqueue() = {
    if (size >= limit) {
      //remove oldest element
    }
    super.enqueue()
  }
}

答案 2 :(得分:4)

这是一个不可改变的解决方案:

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())
}

一个例子:

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)

答案 3 :(得分:0)

这是我扩展Scala的标准mutable.Queue类所采用的方法。

class LimitedQueue[A](maxSize: Int) extends mutable.Queue[A] {
  override def +=(elem: A): this.type = {
    if (length >= maxSize) dequeue()
    appendElem(elem);
    this
  }
}

简单的用例

var q2 = new LimitedQueue[Int](2)
q2 += 1
q2 += 2
q2 += 3
q2 += 4
q2 += 5

q2.foreach { n =>
  println(n)
}

由于旧元素已预先出队,您在控制台中只会看到45