scala custom iterator example

The Iterator Pattern is a behavioral design pattern which provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. This pattern gives you a way to step through the elements of an aggregate without having to know how things are represented under the covers.

When we allow a aggregate class to do more than one thing like taking more responsibilities like iteration then we have given the class two reasons to change. It can change if the collection changes in some way, and it can change if the way we iterate changes. The design principle “A class should have only one reason to change” will be violated if we mix the iteration logic into the aggregate class.

Lets code the iterator pattern for the AlertAggregator class which is basically an aggregator of alerts. We will have a method called iterator which will return our custom iterator which we will be using to iterate over the alert aggregator.

Lets start with the iterator trait


trait CustomIterator[T] {

def hasNext():Boolean;
def next():T

}

Below is the alert domain object


class Alert(var elementId:Int,var metricMetadataId:Int,var metricMetadataHourlyId:Int,var durationType:String,var durationInterval:Int) {

}

Lets code the AlertAggregator which has a method iterator which will return the iterator


class AlertAggregator(val list:ListBuffer[Alert]) {

def iterator():AlertIterator=
{
new AlertIterator(this)
}

}

Lets code the AlertIterator which has the actual implementation of the iteration


import scala.collection.mutable.ListBuffer

class AlertIterator(alertAgg: AlertAggregator) extends CustomIterator[Alert] {

var list: ListBuffer[Alert] = alertAgg.list

var position: Int = 0;

def hasNext(): Boolean =
{
if (position >= list.size) {
return false;
} else {
return true;
}

}
def next(): Alert=
{
val alert=list(position)
position+=1
alert
}

}

Driver code

object Test extends App {

var list=scala.collection.mutable.ListBuffer[Alert]();

var alert1=new Alert(1,2,3,"PW",4);
var alert2=new Alert(2,2,3,"PW",4);
var alert3=new Alert(3,2,3,"PW",4);
var alert4=new Alert(4,2,3,"PW",4);

list +=alert1
list +=alert2
list +=alert3
list +=alert4

var agg=new AlertAggregator(list)

var iterator=agg.iterator()

while(iterator.hasNext())
{
println(iterator.next().elementId)
}

}

I have created an alert iterator code just to show how we can create our own iterators but actually we don’t require this code as ListBuffer already implements the iterator interface and we could have directly returned the same iterator directly.