I have two sorted lists, and want to create an iterator which will merge the two lists in sorted oder. I'm new to Scala and especially new with writing generic classes. I get a compile error that I'm unable to figure out.
Here is the code for MergingIterator
class MergingIterator[ElementType <: Ordered[ElementType]] (iterator1: BufferedIterator[ElementType], iterator2: BufferedIterator[ElementType]) extends Iterator[ElementType]{
override def hasNext: Boolean = {
iterator1.hasNext || iterator2.hasNext
}
override def next(): ElementType = {
if(!iterator1.hasNext && !iterator2.hasNext){
throw new IllegalStateException("All iterators empty. No next element")
}
val e1 : Option[ElementType] = if(iterator1.hasNext) Some(iterator1.head) else None
val e2 : Option[ElementType] = if(iterator2.hasNext) Some(iterator2.head) else None
if(e1.isDefined && e2.isDefined){
val e1a = e1.get
val e2a = e2.get
if(e1a.equals(e2a) || e1a < e2a){
iterator1.next()
}
else {
iterator2.next()
}
}
else if (e1.isDefined){
iterator1.next
}
else if (e2.isDefined){
iterator2.next()
}
else{
throw new Exception("InvalidState. No elements present")
}
}
}
And here is the Unit Test, which is what doesn't compile:
class MergingIteratorTest extends AnyFunSuite {
test("Both Iterators Empty"){
runTest(List(), List(), List())
}
private def runTest(vals1 : List[ComparableInt], vals2: List[ComparableInt], expected: List[ComparableInt]): Unit ={
val it1 = vals1.iterator.buffered
val it2 = vals2.iterator.buffered
val merging = new MergingIterator[ComparableInt](it1, it2)
val merged = merging.toList
assert(expected.equals(merged))
}
case class ComparableInt(value: Int) extends Ordered[Int] {
override def compare(that: Int): Int = value - that
}
}
However when I try to compile, I get the following errors.
Error:(14, 9) type arguments [MergingIteratorTest.this.ComparableInt] do not conform to class MergingIterator's type parameter bounds [ElementType <: Ordered[ElementType]]
val merging = new MergingIterator[ComparableInt](it1, it2)
Error:(14, 23) type arguments [MergingIteratorTest.this.ComparableInt] do not conform to class MergingIterator's type parameter bounds [ElementType <: Ordered[ElementType]]
val merging = new MergingIterator[ComparableInt](it1, it2)
I'm sure it's something stupid that I'm doing wrong, but due to my lack of experience with scala I've been able to figure out what the problem is. Any help here would be appreciated.
You need to make
case class ComparableInt(value: Int) extends Ordered[ComparableInt] {
override def compare(that: ComparableInt): Int = value.value - value.value
}
The issue is in [ElementType <: Ordered[ElementType]]
type bounds - you see ElementType
should be ordered to itself and your case ComparableInt
implements Ordered[Int]
and meaning ComparableInt
is not Ordered
to itself as MergingIterator
signature expects.