Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
scala集合循环缓冲区_Scala_Circular Buffer_Reentrantreadwritelock - Fatal编程技术网

scala集合循环缓冲区

scala集合循环缓冲区,scala,circular-buffer,reentrantreadwritelock,Scala,Circular Buffer,Reentrantreadwritelock,只是在这里胡闹,有循环缓冲区。这是一个合理的实现还是有一种更快/更可靠的方法来剥这只猫的皮 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 ReentrantReadWriteLoc

只是在这里胡闹,有循环缓冲区。这是一个合理的实现还是有一种更快/更可靠的方法来剥这只猫的皮

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()
      }
    }
  }

创作

对现有scala集合类和appender函数的类型声明比“自己滚动”更容易实现。如评论中所述,此实现的性能可能不如“真正的”循环缓冲区,但它只需很少的编码即可完成任务:

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
这意味着您的“CircularBuffer”实际上是一个向量,您现在可以免费获得所有相应的向量方法(filter、map、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)

由于您的缓冲区大小是固定的,所以请使用
数组作为内部表示。您还应该看看中断器,它基本上是一个循环缓冲区gzm0,我不想预先分配整个空间。这就是为什么我有一个大小上限,但在内部使用ArrayBuffer。这是个坏主意吗?请注意:使用循环缓冲区的一个原因是为了避免不断分配新的缓冲区数组和丢弃旧的缓冲区而造成的内存混乱。使用底层的
向量
完全等同于这种策略,即分配数组来容纳新元素,然后在旧元素出列时丢弃数组。如果这是可以接受的,并且您希望在缓冲区已满时丢弃数据而不是阻塞数据,则此实现将起作用,但如果您要处理大量数据,则真正的循环缓冲区将执行得更好。@SarahG指出。我同意true circular buffer的性能比我的实现要好,但考虑到JVM回收内存的方式,以及向量分配内存的方式,我认为改进不会超过一个数量级。因此,这是CPU周期成本和开发人员创建CPU周期时间成本之间的折衷。但是,我已经相应地更新了我的答案。。。