2013-04-30 181 views
5

只是在這裏,與循環緩衝區搞亂。這是一個合理的實施,還是有一個更快/更可靠的方法來剝皮這隻貓?斯卡拉集合循環緩衝區

class CircularBuffer[T](size: Int)(implicit mf: Manifest[T]) { 

    private val arr = new scala.collection.mutable.ArrayBuffer[T]() 

    private var cursor = 0 

    val monitor = new ReentrantReadWriteLock() 

    def push(value: T) { 
     monitor.writeLock().lock() 
     try { 
     arr(cursor) = value 
     cursor += 1 
     cursor %= size 
     } finally { 
     monitor.writeLock().unlock() 
     } 
    } 

    def getAll: Array[T] = { 
     monitor.readLock().lock() 
     try { 
     val copy = new Array[T](size) 
     arr.copyToArray(copy) 
     copy 
     } finally { 
     monitor.readLock().unlock() 
     } 
    } 
    } 
+1

由於您的緩衝區是固定的大小,使用'Array'作爲內部表示。 – gzm0 2013-04-30 16:30:25

+1

你也應該看看干擾器,它基本上是一個循環緩衝區https://github.com/LMAX-Exchange/disruptor – Noah 2013-04-30 16:31:00

+0

gzm0,我不想分配整個空間,預先。這就是爲什麼我有一個大小上限,但內部使用ArrayBuffer。這是一個壞主意嗎? – irishjava 2013-05-01 15:36:57

回答

3

創作

我會使用類型聲明和一個加法器的功能,而不是「滾你自己」:

import scala.collection.immutable 

type CircularBuffer[T] = immutable.Vector[T] 

def emptyCircularBuffer[T] : CircularBuffer[T] = immutable.Vector.empty[T] 

def addToCircularBuffer[T](maxSize : Int)(buffer : CircularBuffer[T], item : T) : CircularBuffer[T] = 
    (buffer :+ item) takeRight maxSize 

這意味着你的「環形緩衝區」實際上是一個向量,你現在可以免費獲取所有相應的Vector方法(過濾器,地圖,flatMap等...):

var intCircularBuffer = emptyCircularBuffer[Int] 

//Vector(41) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 41) 

//Vector(41, 42) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 42) 

//Vector(42, 43) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 43) 

//Vector(42) 
val evens : CircularBuffer[Int] = intCircularBuffer filter (_ % 2 == 0) 

索引

您同樣可以添加一個功能圓形索引:

def circularIndex[T](buffer : CircularBuffer[T])(index : Int) : T = 
    buffer(index % buffer.size)