簡體   English   中英

Scala 隊列的最大長度

[英]Maximum Length for scala queue

我很好奇 Scala 是否在我可以使用的集合類中隱藏了一些 gem。 基本上我正在尋找類似 FIFO 隊列的東西,但是它的大小有上限,這樣當達到限制時,最舊的(第一個)元素將從隊列中刪除。 過去我自己在 Java 中實現了這一點,但如果可能的話,我寧願使用標准的東西。

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

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++等操作構造的那些。

更新:正如 Dylan 在評論中所說, enqueueFinite還需要為最大隊列大小取一個參數,並根據需要刪除元素。 我更新了代碼。

為什么不只是將 FIFO 隊列子類化? 像這樣的東西應該可以工作:(偽代碼如下......)

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

這是一個不可變的解決方案:

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)

這是我在擴展 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 ,因為舊元素事先已出列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM