2013-04-30 18 views
5

Basta fare casino qui, con buffer circolari. Si tratta di un'implementazione ragionevole o esiste un modo più rapido/più affidabile per rivestire questo gatto?buffer circolare di collezioni scala

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

Poiché il buffer è di dimensione fissa, utilizzare un 'Array' come rappresentazione interna. – gzm0

+1

Dovresti anche dare un'occhiata al disruptor, è fondamentalmente un buffer circolare https://github.com/LMAX-Exchange/disruptor – Noah

+0

gzm0, non volevo allocare l'intero spazio, in anticipo. Ecco perché ho un limite superiore alla dimensione ma uso internamente un ArrayBuffer. È una cattiva idea? – irishjava

risposta

3

Creazione

userei dichiarazione di tipo e una funzione di vipera invece "rolling your own":

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 

Ciò significa che il "CircularBuffer" è in realtà un vettore e si ora ottieni tutti i metodi vettoriali corrispondenti (filtro, mappa, flatMap, ecc ...) gratuitamente:

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) 

indicizzazione

È possibile aggiungere una funzione simile per l'indicizzazione circolare:

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