2011-08-02 8 views
12

私が使用できるコレクションクラスに隠された宝石がScalaにあるかどうか不思議です。基本的に私はFIFOキューのようなものを探していますが、上限に達したときに最も古い(最初の)要素がキューから削除されるようなサイズの上限があります。私は過去に自分自身をJavaで実装しましたが、可能であれば何か標準を使用したいと思います。スカラキューの最大長

答えて

19

サブクラスにアンしばしば望ましい選択肢は、(残念ながらという名前の)「pimp my library」パターンです。あなたはそうのように、QueueenqueueFiniteメソッドを追加するためにそれを使用することができます:

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がスコープ内にあるときはいつでも、彼らはenqueueFinite方法持っているかのように、あなたがQueueオブジェクトを扱うことができます。

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) 

利点をこのアプローチのサブクラス化には、enqueue,map++などの操作で構築されたものを含め、QueueすべてでenqueueFiniteが使用可能であることがあります。

更新:ディランはコメントで言うように、enqueueFiniteニーズも最大キューサイズのためのパラメータを取り、必要に応じて要素をドロップします。私はコードを更新しました。ここで

+0

Cool。しかし、どのように最大キューサイズを渡すのですか? – paradigmatic

+0

私は2つのオプションがあります:あなたの有限のキューは変更可能です。変更後のサイズを変更した場合(必要に応じて要素を削除します)、キューを変更できない場合は、その制限を '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)