First of all, apologies for introducing a new word.
But it seemed like a good idea to draw attention to the similarity between iteration and stream processing constructs.
So, "striteration" is a term to indicate a combination of both Streams and Iteration.
The Striterator object implements the Iterator and the Enumeration
interfaces along with the additional methods that add support for stream type processing
functionality.
Probably the best way to explain Striteration is to give a number of examples.
A Striterator must initially be given an Iterator object.
For example :
Striterator striter = new Striterator(list.iterator());
The resulting Striterator can be used anywhere an Iterator or
Enumeration is required.
Want to "append" two iterators?
striter.addFilter(new Appender(otherList.iterator()));
In fact, this is such a common requirement, that a utility is provided on
the Striterator object.
striter.append(otherList.iterator());
Need to "filter out" certain objects?
striter.addFilter(new Filter() {
protected boolean isValid(Object obj) {
return obj instanceof SomeClass;
}
} );
Would provide a type check on each object.
Often, the object of interest is not the object directly in the iteration:
public Iterator getNames(Iterator members) {
Striterator names = new Striterator(members);
return names.addFilter(new Resolver() {
protected Object resolve(Object obj) {
return ((NamedType) obj).getName();
}
} );
}
With this example one of the features of Striteration is apparent, that
you are able to create new iterators to be processed elsewhere.
It can be used to provide set abstractions in a similar way to SQL type database queries.
Along with resolving the requirement to expand sets is also
common. Consider some getGrandchildren method :
public Iterator getGrandChildren() {
Striterator gchildren = new Striterator(getChildren());
return gchildren.addFilter(new Expander() {
protected Iterator expand(Object obj) {
return ((Human) obj).getChildren();
}
} );
}
You may have realised that the addFilter must be returning an
Iterator. In fact it returns a Striterator so that
filters can be chained together.
Let's use Striterator declarations and see how much neater things get:
public Striterator getNames(Striterator members) {
return members.addFilter(new Resolver() {
protected Object resolve(Object obj) {
return ((NamedType) obj).getName();
}
} );
}
public Striterator getChildren() {
return new Striterator(m_children.iterator());
}
public Striterator getGrandChildren() {
return getChildren().addFilter(new Expander() {
protected Iterator expand(Object obj) {
return ((Human) obj).getChildren();
}
} );
}
public void printGrandchildrenNames() {
Striterator gcnames = getNames(getGrandChildren());
while (gcnames.hasNext()) {
System.out.println(gcnames.next());
}
}
There are a number of other patterns already provided for :
The Striterator protocol is designed so that it is easy to add new
patterns.
A few other classes are provided to support Striterator constructs.
Takes an Enumeration object to provide an Iterator
Just what it says - a final class implementing Iterator but is always
empty. Very handy!
Just what it says - a final class implementing Iterator that is initialised
with the single object it will return. Also very useful.