Immutable List

An example of the the ImmutableCollection JavaIdiom. Here's the code; use at your own risk...

import java.util.Enumeration;
public abstract class ImmutableList
{
/** Adds an element to the head of the list, returning the new list.
*
public final ImmutableList add( Object o ) {
return new Node( o, this );
}
/** Removes the element o resulting in a new list which
*
*
public abstract ImmutableList remove( Object o );
/** Removes all elements for which the predicate p returns
*
public abstract ImmutableList 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
public abstract ImmutableList 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 ImmutableList _current = ImmutableList.this;
};
}
/** The empty list. Variables of type ImmutableList should be
public static final ImmutableList EMPTY = new ImmutableList() {
public ImmutableList removeIf( Predicate p ) {
return this;
}
public ImmutableList remove( Object o ) {
return this;
}
public void forAll( Procedure proc ) {
return;
}
public ImmutableList map( Function fn ) {
return this;
}
};
static class Node extends ImmutableList {
Node( Object element, ImmutableList next ) {
_element = element;
_next = next;
}
Node( Object element ) {
_element = element;
_next = EMPTY;
}
public ImmutableList removeIf( Predicate p ) {
ImmutableList n = _next.remove(p);
if( p.evaluate(_element) ) {
return n;
} else if( n == _next ) {
return this;
} else {
return new Node( _element, n );
}
}
public ImmutableList remove( Object old ) {
if( _element == old ) {
return _next;
} else {
ImmutableList 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 ImmutableList map( Function fn ) {
return new Node( fn.evaluate(_element), _next.map(fn) );
}
private Object _element;
private ImmutableList _next;
}
}

Take a look at BlocksInJava for ways to create the Functions, Procedures, and Predicates uses by the InternalIterators of this class. In BlocksForJava these are called UnaryPredicate, UnaryFunction, and UnaryProcedure. 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 UnitTests? --PCP

(It's prob'ly the weekend where he is too...)

He probably has them in the ImmutableListTest class that is a subclass of junit.framework.TestCase. Or did you also want all the testing code? :)


CategoryObjectFunctionalPatterns CategoryClosure CategoryCollections