An example of the the ImmutableCollection JavaIdiom. Here's the code; use at your own risk...
import java.util.Enumeration;
public abstract class Immutable''''''List
{
/** Adds an element to the head of the list, returning the new list.
*
* @param o
* The element to be added to the list.
* @return
* The list consisting of the element o followed by
* this list.
*/
public final Immutable''''''List add( Object o ) {
return new Node( o, this );
}
/** Removes the element o resulting in a new list which
* is returned to the caller.
*
* @param o
* The object to be removed from the list.
*
* @return
* A list consisting of this list with object o removed.
*/
public abstract Immutable''''''List remove( Object o );
/** Removes all elements for which the predicate p returns
* true, resulting in a new list which is returned to the caller.
*
* @param p
* A predicate that returns true
if the element is
* to be removed from the list, and false
otherwise.
* @return
* A list consisting of this list with all elements for which the
* predicate p returned true removed.
*/
public abstract Immutable''''''List removeIf( Predicate p );
/** Applies the procedure proc to all elements in the list.
*/
public abstract void forAll( Procedure proc );
/** Creates a new list whose elements are the result of applying function
* fn to the elements of this list.
*/
public abstract Immutable''''''List map( Function fn );
/** Returns a "standard" enumeration over the elements of the list.
*/
public Enumeration elements() {
return new Enumeration() {
public boolean hasMoreElements() {
return _current != EMPTY;
}
public Object nextElement() {
Object result = ((Node)_current)._element;
_current = ((Node)_current)._next;
return result;
}
private Immutable''''''List _current = Immutable''''''List.this;
};
}
/** The empty list. Variables of type Immutable''''''List should be
* initialised to this value to create new empty lists.
*/
public static final Immutable''''''List EMPTY = new Immutable''''''List() {
public Immutable''''''List removeIf( Predicate p ) {
return this;
}
public Immutable''''''List remove( Object o ) {
return this;
}
public void forAll( Procedure proc ) {
return;
}
public Immutable''''''List map( Function fn ) {
return this;
}
};
static class Node extends Immutable''''''List {
Node( Object element, Immutable''''''List next ) {
_element = element;
_next = next;
}
Node( Object element ) {
_element = element;
_next = EMPTY;
}
public Immutable''''''List removeIf( Predicate p ) {
Immutable''''''List n = _next.remove(p);
if( p.evaluate(_element) ) {
return n;
} else if( n == _next ) {
return this;
} else {
return new Node( _element, n );
}
}
public Immutable''''''List remove( Object old ) {
if( _element == old ) {
return _next;
} else {
Immutable''''''List n = _next.remove(old);
if( n == _next ) {
return this;
} else {
return new Node( _element, n );
}
}
}
public void forAll( Procedure proc ) {
proc.execute(_element);
_next.forAll(proc);
}
public Immutable''''''List map( Function fn ) {
return new Node( fn.evaluate(_element), _next.map(fn) );
}
private Object _element;
private Immutable''''''List _next;
}
}
Take a look at BlocksInJava for ways to create the Functions, Procedures, and Predicates uses by the InternalIterator''''''s of this class. In BlocksForJava these are called ''U''''''naryPredicate'', ''U''''''naryFunction'', and ''U''''''naryProcedure''. There is also a helper class called ''Block'' that allows you to type ''new Block() {...}'' for each one of these.
----
Nice code. But - hey! Where's the UnitTest''''''s? --PCP
(It's prob'ly the weekend where he is too...)
He probably has them in the ''I''''''mmutableListTest'' class that is a subclass of ''junit.framework.T''''''estCase''. Or did you also want all the testing code? :)
----
CategoryObjectFunctionalPatterns CategoryClosure CategoryCollections