iterator pattern java 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 interface


public interface CustomIterator<T> {

public boolean hasnext();
public T next();

}

Below is the alert domain object

public class Alert implements Cloneable {

private int subElementId;
private int metricMetadataId;
private int metricMetadataHourlyId;
private float metricValue;

public Alert(int subElementId, int metricMetadataId, int metricMetadataHourlyId, float metricValue) {
super();
this.subElementId = subElementId;
this.metricMetadataId = metricMetadataId;
this.metricMetadataHourlyId = metricMetadataHourlyId;
this.metricValue = metricValue;

}

public int getSubElementId() {
return subElementId;
}

public void setSubElementId(int subElementId) {
this.subElementId = subElementId;
}

public int getMetricMetadataId() {
return metricMetadataId;
}

public void setMetricMetadataId(int metricMetadataId) {
this.metricMetadataId = metricMetadataId;
}

public int getMetricMetadataHourlyId() {
return metricMetadataHourlyId;
}

public void setMetricMetadataHourlyId(int metricMetadataHourlyId) {
this.metricMetadataHourlyId = metricMetadataHourlyId;
}

public float getMetricValue() {
return metricValue;
}

public void setMetricValue(float metricValue) {
this.metricValue = metricValue;
}

}

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


public class AlertAggregator {

public List<Alert> alertList;

public AlertAggregator(List<Alert> alertList) {
super();
this.alertList = alertList;
}

public List<Alert> getAlertList() {
return alertList;
}

public void setAlertList(List<Alert> alertList) {
this.alertList = alertList;
}

public CustomIterator<Alert> iterator() {
return new AlertIterator(this);
}

}

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


public class AlertIterator implements CustomIterator<Alert> {

private List<Alert> list;

private int position;

public AlertIterator(AlertAggregator aa) {
super();
list = aa.getAlertList();
}

@Override
public boolean hasnext() {

if (list.size() <= position) {
return false;
} else {
return true;
}

}

@Override
public Alert next() {
// TODO Auto-generated method stub
Alert alert = list.get(position);
position++;
return alert;
}

}

Driver code

public class Test {

public static void main(String[] args) {

List<Alert> list = new ArrayList<Alert>();
list.add(new Alert(1, 2, 3, 4.5f));
list.add(new Alert(2, 2, 3, 4.5f));
list.add(new Alert(3, 2, 3, 4.5f));
list.add(new Alert(4, 2, 3, 4.5f));

AlertAggregator aa = new AlertAggregator(list);

CustomIterator<Alert> alertList=aa.iterator();

while (alertList.hasnext()) {

System.out.println(alertList.next().getSubElementId());

}

}

}

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 list already implements the iterator interface and we could have directly returned the same iterator directly.