如何实现支持循环迭代和删除的类

时间:2017-01-18 06:20:16

标签: scala

我有一个类,应该支持循环迭代和删除:

class CircularTest {

    private val set = mutable.LinkedHashSet[String]("1", "2", "3", "4", "5")

    private val circularIter: Iterator[String] = Iterator.continually(set).flatten

    def selectNext: String = {
      circularIter.next()
    }

    def remove(v: String): Unit = {
      set.remove(v)
    }
  }

这不起作用。

简单测试,应该有效:

val circularTest = new CircularTest

circularTest.selectNext shouldEqual "1"
circularTest.selectNext shouldEqual "2"

circularTest.remove("3")
circularTest.remove("5")

circularTest.selectNext shouldEqual "4" // actual "3"
circularTest.selectNext shouldEqual "1"

如何实现此功能?或者也许没有迭代器的其他解决方案?

1 个答案:

答案 0 :(得分:1)

嗯......问题是Iterator.continually在这种情况下会给你一种不可改变的东西。这意味着即使您更改了集合的内容,它也不会对迭代器产生任何影响。

实际上你可以通过在remove方法中更新迭代器本身来解决这个问题。

class CircularTest {

  private var set = Set[String]("1", "2", "3", "4", "5")

  private var circularIter: Iterator[String] = Iterator.continually(set).flatten

  def selectNext: String = this.synchronized {
    circularIter.next()
  }

  def remove(v: String): Unit = this.synchronized {
    set = set.remove(v)
    circularIter = Iterator.continually(set).flatten
  }
}

但更好的方法是以适当的方式实际实现自己的迭代器。

import scala.collection.immutable.HashSet
import scala.collection.mutable.ArrayBuffer

class MyCircularIterator[T] extends Iterator[T] {

  private var index: Int = 0
  private var set: mutable.LinkedHashSet[T] = mutable.LinkedHashSet()
  private var vector: Vector[T] = Vector()
  private var vectorSize: Int = 0


  override def hasNext: Boolean = this.synchronized {
    set.size match {
      case 0 => false
      case _ => true
    }
  }

  // Iterator does not define `next()` behavior whe hasNext == false;
  // here it will just throw IndexOutOfBoundsException
  override def next(): T = this.synchronized {
    index = index % vectorSize
    val next = vector(index)
    index = index + 1
    next
  }

  def add(t: T*): Unit = this.synchronized {
    set = set ++ t
    vector = Vector(set.toList: _*)
    vectorSize = vector.length
  }

  def remove(t: T*): Unit = this.synchronized {
    set = set -- t
    vector = Vector(set.toList: _*)
    vectorSize = vector.length
  }

}

object MyCircularIterator {

  def apply[T](hashSet: HashSet[T]): MyCircularIterator[T] = {
    val iter = new MyCircularIterator[T]()
    iter.add(hashSet.toList: _*)
    iter
  }

}

现在你可以像这样使用它,

val myCircularIterator = MyCircularIterator(HashSet[Int](1, 2, 3, 4, 5))

myCircularIterator.next()
// 1
myCircularIterator.next()
// 2
myCircularIterator.remove(3, 5)
myCircularIterator.next()
// 4
myCircularIterator.next()
// 1