Just messing about here, with circular buffers. Is this a sensible implementation or is there a faster/more reliable way to skin this cat?
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()
}
}
}
Creation
A type declaration to an existing scala collection class and an appender function is easier to implement than "rolling your own". As noted in the comments this implementation will likely not be as performant as a "true" circular buffer, but it gets the job done with very little coding:
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
This means that your "CircularBuffer" is actually a Vector and you now get all of the corresponding Vector methods (filter, map, flatMap, etc...) for free:
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
You can similarly add a function for circular indexing:
def circularIndex[T](buffer : CircularBuffer[T])(index : Int) : T =
buffer(index % buffer.size)
来源:https://stackoverflow.com/questions/16304695/scala-collections-circular-buffer