2011-08-02 63 views
12

我很好奇斯卡拉是否有一些隐藏在我可以使用的集合类中的gem。基本上我正在寻找像FIFO队列这样的东西,但是它的大小有一个上限,这样当限制被击中时,最老的(第一个)元素将从队列中移除。我过去在Java中自己实现了这一点,但如果可能的话,我宁愿使用标准的东西。scala队列的最大长度

回答

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,包括那些通过如enqueue,map,++等操作构建的那些

更新:正如Dylan在评论中所述,enqueueFinite还需要为最大队列大小取一个参数,并根据需要放置元素。我更新了代码。

+0

很酷。但是,你如何通过最大队列大小? – paradigmatic

+0

我看到两个选项:你的有限队列是可变的,在这种情况下,你可以在创建它之后更改大小(如果需要删除元素),或者你的队列是不可变的,在这种情况下,你会将限制添加到'enqueueFinite'方法。 – Dylan

+0

或者你可以添加一个隐式的'Int'参数。 – Jus12

4

为什么你不只是子类化FIFO队列?像这样的东西应该工作:(伪如下...)

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

另一种选择是使用“我的派普图书馆”图案到'enqueueFinite'方法添加到队列类。这似乎是可取的,因为它避免了通常的方法('map','++',...) –

+0

@Kipton的类型问题,你应该自己做出答案。我认为这确实是最好的。 –

+0

完成,谢谢您的建议。 –

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)