我有一个类,应该支持循环迭代和删除:
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"
如何实现此功能?或者也许没有迭代器的其他解决方案?
答案 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