Share on Facebook Share on Twitter Email
Answers.com

Iterator pattern

 
Wikipedia: Iterator pattern

In object-oriented programming, the Iterator pattern is a design pattern in which iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation. An Iterator object encapsulates the internal structure of how the iteration occurs.

For example, a tree, linked list, hash table, and an array all need to be iterated with the methods search, sort, and next. Rather than having 12 different methods to manage (one implementation for each of the previous three methods in each structure), using the iterator pattern yields just seven: one for each class using the iterator to obtain the iterator and one for each of the three methods. Therefore, to run the search method on the array, you would call array.search(), which hides the call to array.iterator.search().

Contents

Examples

Java

import java.util.*; 
public class BitSetIterator implements Iterator<Boolean> { 
	private final BitSet bitset; 
	private int index;
 
	public BitSetIterator(BitSet bitset) { 
		this.bitset = bitset; 
	}
 
	public boolean hasNext() {   
		return index < bitset.length(); 
	} 
 
	public Boolean next() { 
		if (index >= bitset.length()) { 
			throw new NoSuchElementException(); 
		} 
		boolean b = bitset.get(index++); 
		return new Boolean(b); 
	} 
 
	public void remove() { 
		throw new UnsupportedOperationException(); 
	}
}

Two different usage examples:

public class TestClientBitSet { 
	public static void main(String[] args) { 
		// create BitSet and set some bits 
		BitSet bitset = new BitSet(); 
		bitset.set(1); 
		bitset.set(3400); 
		bitset.set(20); 
		bitset.set(47); 
		BitSetIterator iter = new BitSetIterator(bitset); 
		while (iter.hasNext()) { 
			Boolean b = iter.next();               
			String tf = (b.booleanValue() ? "T" : "F"); 
			System.out.print(tf); 
		} 
		System.out.println(); 
	} 
} 
 
import java.util.*; 
public class TestClientIterator  {
	public static void main(String[] args) { 
		ArrayList<Object> al = new ArrayList<Object>(); 
		al.add(new Integer(42)); 
		al.add(new String("test")); 
		al.add(new Double("-12.34")); 
		for(Iterator<Object> iter=al.iterator(); 
		iter.hasNext();) 
		System.out.println( iter.next() ); 
		// JEE5 syntax 
		for(Object o:al) 
		System.out.println( o ); 
	} 
}

PHP 5

As a default behavior in PHP 5, using an object in a foreach structure will traverse all public values. Multiple Iterator classes are available with PHP to allow you to iterate through common lists, such as directories, XML structures and recursive arrays.

It's possible to define your own Iterator classes by implementing the Iterator interface, which will override the default behavior.

The Iterator interface definition:

interface Iterator
{
    // Returns the current value
    function current();
 
    // Returns the current key
    function key();
 
    // Moves the internal pointer to the next element
    function next();
 
    // Moves the internal pointer to the first element
    function rewind();
 
    // If the current element is not at all valid (boolean)
    function valid();
}

These methods are all being used in a complete foreach( $object as $key=>$value ) sequence. The methods are executed in the following order:

rewind() 
while valid() {
    current() in $value 
    key() in $key 
    next()
} 
End of Loop

According to Zend, the current() method is called before and after the valid() method.

C++

The following C++ program gives the implementation of iterator design pattern with generic C++ template:

/************************************************************************/
/* Iterator.h                                                           */
/************************************************************************/
#ifndef MY_ITERATOR_HEADER
#define MY_ITERATOR_HEADER
 
//////////////////////////////////////////////////////////////////////////
template<class T,class U>
class Iterator
{
public:
	typedef typename std::vector<T>::iterator iter_type;
	Iterator(U*  pData):m_pData(pData){
		m_it = m_pData->m_data.begin();
	}
 
	void first()
	{
		m_it = m_pData->m_data.begin();
	}
 
	void next()
	{
		m_it++;
	}
 
	bool isDone()
	{
		return (m_it == m_pData->m_data.end());
	}
 
	typename iter_type current()
	{
		return m_it;
	}
private:
	U* m_pData;
	typename iter_type m_it;
};
 
template<class T,class U,class A>
class setIterator
{
public:
	typedef typename std::set<T,U>::iterator iter_type;
 
	setIterator(A* pData):m_pData(pData)
	{
		m_it = m_pData->m_data.begin();
	}
 
	void first()
	{
		m_it = m_pData->m_data.begin();
	}
 
	void next()
	{
		m_it++;
	}
 
	bool isDone()
	{
		return (m_it == m_pData->m_data.end());
	}
 
	iter_type current()
	{
		return m_it;
	}
 
private:
	A*				m_pData;		
	iter_type		m_it;
};
#endif
/************************************************************************/
/* Aggregate.h                                                          */
/************************************************************************/
#ifndef MY_DATACOLLECTION_HEADER
#define MY_DATACOLLECTION_HEADER
 
#include "Iterator.h"
 
template <class T>
class aggregate
{
	friend Iterator<T,aggregate>;
public:
	void add(T a)
	{
		m_data.push_back(a);
	}
 
	Iterator<T,aggregate>* create_iterator()
	{
		return new Iterator<T,aggregate>(this);
	}
 
 
private:
	std::vector<T> m_data;
};
template <class T,class U>
class aggregateSet
{
	friend setIterator<T,U,aggregateSet>;
public:
	void add(T a)
	{
		m_data.insert(a);
	}
 
	setIterator<T,U,aggregateSet>* create_iterator()
	{
		return new setIterator<T,U,aggregateSet>(this);
	}
 
	void Print()
	{
		copy(m_data.begin(),m_data.end(),ostream_iterator<T>(cout,"\r\n"));
	}
 
protected:
private:
	std::set<T,U> m_data;
};
 
#endif
/************************************************************************/
/* Iterator Test.cpp                                                    */
/************************************************************************/
#include <iostream>
#include <vector>
#include <set>
#include "Aggregate.h"
using namespace std;
 
class Money
{
public:
	Money(int a=0):m_data(a){}
 
	void SetMoney(int a){
		m_data = a;
	}
 
	int GetMoney()
	{
		return m_data;
	}
 
protected:
private:
	int m_data;
};
 
class Name
{
public:
	Name(string name):m_name(name){}
 
	const string& GetName() const{
		return m_name;
	}
 
	friend ostream& operator<<(ostream& cout,Name name)
	{
		cout<<name.GetName();
		return cout;
	}
 
private:
	string m_name;
};
 
struct NameLess
{
	bool operator() ( const Name& lhs, const Name& rhs) const
	{
		return lhs.GetName() < rhs.GetName();
	}
};
 
int main( void ) {
		//sample 1
	cout<<"________________Iterator with int______________________________________"<<endl;
	aggregate<int> agg;
 
	for(int i=0;i<10;i++)
	{
		agg.add(i);
	}
 
 
	Iterator< int,aggregate<int> > *it = agg.create_iterator();
	for(it->first();!it->isDone();it->next())
	{
		cout<<*it->current()<<endl;
	}
 
 
	//sample 2
	aggregate<Money> agg2;
	Money a(100),b(1000),c(10000);
	agg2.add(a);
	agg2.add(b);
	agg2.add(c);
 
	cout<<"________________Iterator with Class Money______________________________"<<endl;
	Iterator< Money,aggregate<Money> > *it2 = agg2.create_iterator();
	it2->first();
	while (!it2->isDone()) {
		cout<<((Money*)(it2->current()))->GetMoney()<<endl;
		it2->next();
	}
 
	//sample 3
	cout<<"________________Set Iterator with Class Name______________________________"<<endl;
 
	aggregateSet<Name,NameLess> aset;
	aset.add(Name("Qmt"));
	aset.add(Name("Bmt"));
	aset.add(Name("Cmt"));
	aset.add(Name("Amt"));
 
 
	setIterator<Name,NameLess,aggregateSet<Name,NameLess>  > * it3 = aset.create_iterator();
	for(it3->first();!it3->isDone();it3->next())
	{
		cout<<(*it3->current())<<endl;
	}
}

Console output:

________________Iterator with int______________________________________
0
1
2
3
4
5
6
7
8
9
________________Iterator with Class Money______________________________
100
1000
10000
________________Set Iterator with Class Name___________________________
Amt
Bmt
Cmt
Qmt

Ruby

Iterate over the members of an array.

numbers = [1,2,3,4,5,6]
numbers.each {|i| puts "I got #{i}"}

Ouputs:

I got 1
I got 2
I got 3
I got 4
I got 5
I got 6

MATLAB

MATLAB supports both external and internal implicit iteration using either "native" arrays or cell arrays. In the case of external iteration where the onus is on the user to advance the traversal and request next elements, one can define a set of elements within an array storage structure and traverse the elements using the for-loop construct. For example,

% Define an array of integers
myArray = [1,3,5,7,11,13];
 
for n = myArray
   % ... do something with n
   disp(n)  % Echo integer to Command Window
end

traverses an array of integers using the for keyword.

In the case of internal iteration where the user can supply an operation to the iterator to perform over every element of a collection, many built-in operators and MATLAB functions are overloaded to execute over every element of an array and return a corresponding output array implicitly. Furthermore, the arrayfun and cellfun functions can be leveraged for performing custom or user defined operations over "native" arrays and cell arrays respectively. For example,

function simpleFun
% Define an array of integers
myArray = [1,3,5,7,11,13];
 
% Perform a custom operation over each element 
myNewArray = arrayfun(@(a)myCustomFun(a),myArray);
 
% Echo resulting array to Command Window          
myNewArray
 
 
function outScalar = myCustomFun(inScalar)
% Simply multiply by 2
outScalar = 2*inScalar;

defines a primary function simpleFun which implicitly applies custom subfunction myCustomFun to each element of an array using built-in function arrayfun.

Alternatively, it may be desirable to abstract the mechanisms of the array storage container from the user by defining a custom object-oriented MATLAB implementation of the Iterator Pattern. Such an implementation supporting external iteration is demonstrated in MATLAB Central File Exchange item Design Pattern: Iterator (Behavioural). This is written in the new class-definition syntax introduced with MATLAB software version 7.6 (R2008a) [1] and features a one-dimensional cell array realisation of the List Abstract Data Type (ADT) as the mechanism for storing a heterogeneous (in data type) set of elements. It provides the funcitonality for explicit forward List traversal with the hasNext(), next() and reset() methods for use in a while-loop.

See also

References

External links

  • Jt J2EE Pattern Oriented Framework



Search unanswered questions...
Enter a question here...
Search: All sources Community Q&A Reference topics
 
 

 

Copyrights:

Wikipedia. This article is licensed under the Creative Commons Attribution/Share-Alike License. It uses material from the Wikipedia article "Iterator pattern" Read more