GeoTools does not have any native ability to "Join" FeatureCollections; even though this is a very common request!
In addition to the example on this page you can find other examples in the validation module.
Joining two Shapefiles
The following example is adapted from some work Gabriella Turk posted to the geotools-user email list. The origional source code is always available in svn at the following link:
Here is the interesting bit from the above file:
private static void joinExample( FeatureSource shapes, FeatureSource shapes2 ) throws Exception { SimpleFeatureType schema = shapes.getSchema(); String typeName = schema.getTypeName(); String geomName = schema.getDefaultGeometry().getLocalName(); SimpleFeatureType schema2 = shapes2.getSchema(); String typeName2 = schema2.getTypeName(); String geomName2 = schema2.getDefaultGeometry().getLocalName(); FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); DefaultQuery outerGeometry = new DefaultQuery( typeName, Filter.INCLUDE, new String[]{ geomName } ); FeatureCollection outerFeatures = shapes.getFeatures( outerGeometry ); FeatureIterator iterator = outerFeatures.features(); int max = 0; try { while( iterator.hasNext() ){ SimpleFeature feature = (SimpleFeature) iterator.next(); try { Geometry geometry = (Geometry) feature.getDefaultGeometry(); if( !geometry.isValid()) { // skip bad data continue; } Filter innerFilter = ff.intersects( ff.property(geomName2), ff.literal( geometry )); DefaultQuery innerQuery = new DefaultQuery( typeName2, innerFilter, DefaultQuery.NO_NAMES ); FeatureCollection join = shapes2.getFeatures( innerQuery ); int size = join.size(); max = Math.max( max, size ); } catch( Exception skipBadData ){ } } } finally { iterator.close(); } System.out.println("At most "+max+" "+typeName2+" features in a single "+typeName+" feature"); }
Sample Output
When run on the uDig sample dataset available here:
You can learn the by running the example as is (using an intersects test):
Welcome to GeoTools:2.5.SNAPSHOT
At most 88 bc_pubs features in a single bc_municipality feature
Other Examples
Here are a couple other examples for innerFilter to think about:
ff.intersects( ff.property(geomName2), ff.literal( geometry )); // 88 pubs ff.dwithin(ff.property(geomName2), ff.literal( geometry ),1.0,"km"); // 60 pubs ff.not( ff.disjoint(ff.property(geomName2), ff.literal( geometry )) ); // 135 pubs! ff.beyond(ff.property(geomName2), ff.literal( geometry ),1.0,"km"); // 437 pubs