2013-04-30 11 views
5

Nur herumspielen, mit kreisförmigen Puffern. Ist das eine sinnvolle Umsetzung oder gibt es eine schnellere/zuverlässigere Methode, diese Katze zu häuten?scala collections circular buffer

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

Da Ihr Puffer fester Größe ist, verwenden Sie eine 'Array' als interne Darstellung. – gzm0

+1

Sie sollten auch einen Blick auf den Disruptor werfen, es ist im Grunde ein Ringspeicher https://github.com/LMAX-Exchange/disruptor – Noah

+0

gzm0, ich wollte nicht den gesamten Speicherplatz, im Voraus reservieren. Deshalb habe ich eine Obergrenze für die Größe, verwende aber intern einen ArrayBuffer. Ist das eine schlechte Idee? – irishjava

Antwort

3

Creation

I Typdeklaration und eine Additionsfunktion stattdessen „Ihre eigenen Rollen“ verwenden würde:

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 

Dies bedeutet, dass Ihre „digitaler ringspeicher“ ist eigentlich ein Vektor und Sie Jetzt erhalten Sie alle entsprechenden Vector-Methoden (Filter, Map, FlatMap, etc ...) kostenlos:

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) 

Indexing

Sie in ähnlicher Weise eine Funktion für Rund Indizierung hinzufügen:

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