The easiest way to answer this sort of question is to do some experimenting, so I tried out some quick and dirty tests using the Natural Earth populated places and admin countries - 7322 points and 177 polygons, and 3 test methods:
One that loops across the points doing a contains
query (like you do):
public static HashMap<String, Integer> pointLoop(SimpleFeatureCollection points, SimpleFeatureCollection polys,
Expression propertyName) {
long start = System.currentTimeMillis();
HashMap<String, Integer> results = new HashMap<>();
try (SimpleFeatureIterator itr = points.features()) {
while (itr.hasNext()) {
SimpleFeature point = itr.next();
Filter filter = filterFactory.contains(propertyName, filterFactory.literal(point.getDefaultGeometry()));
SimpleFeatureCollection sub = polys.subCollection(filter);
try (SimpleFeatureIterator fs = sub.features()) {
while (fs.hasNext()) {
SimpleFeature ff = fs.next();
String name = (String) ff.getAttribute("NAME");
if (results.containsKey(name)) {
int count = results.get(name);
results.put(name, count + 1);
} else {
results.put(name, 1);
}
}
}
}
}
long end = System.currentTimeMillis();
System.out.println("PointLoop Time = " + (end - start) + "ms");
return results;
}
One that loops over the polygons and counts the points:
public static HashMap<String, Integer> polygonLoop(SimpleFeatureCollection points, SimpleFeatureCollection polys,
Expression propertyName) {
long start = System.currentTimeMillis();
HashMap<String, Integer> results = new HashMap<>();
try (SimpleFeatureIterator itr = polys.features()) {
while (itr.hasNext()) {
SimpleFeature poly = itr.next();
Filter filter = filterFactory.within(propertyName, filterFactory.literal(poly.getDefaultGeometry()));
SimpleFeatureCollection sub = points.subCollection(filter);
results.put((String) poly.getAttribute("NAME"), sub.size());
}
}
long end = System.currentTimeMillis();
System.out.println("Polygon Loop Time = " + (end - start) + "ms");
return results;
}
and finally one that uses a SpatialIndexFeatureCollection
on the points to improve the speed of the point in polygon query:
public static HashMap<String, Integer> polygonLoopIndex(SimpleFeatureCollection points, SimpleFeatureCollection polys,
Expression propertyName) throws IOException {
long start = System.currentTimeMillis();
HashMap<String, Integer> results = new HashMap<>();
SpatialIndexFeatureCollection index = new SpatialIndexFeatureCollection(points);
try (SimpleFeatureIterator itr = polys.features()) {
while (itr.hasNext()) {
SimpleFeature poly = itr.next();
Filter filter = filterFactory.within(propertyName, filterFactory.literal(poly.getDefaultGeometry()));
SimpleFeatureCollection sub = index.subCollection(filter);
results.put((String) poly.getAttribute("NAME"), sub.size());
}
}
long end = System.currentTimeMillis();
System.out.println("Indexed Polygon Loop Time = " + (end - start) + "ms");
return results;
}
I got the following results:
Point Loop Time = 3566ms
Polygon Loop Time = 151ms
Indexed Polygon Loop Time = 186ms
so the polygon by polygon loop wins. But I then turned up the size of the points collection and this is the result:
500,000 points
177 polygons
Point Loop Time = 146.029s
Polygon Loop Time = 12.517s
Indexed Polygon Loop Time = 2.801s
So beyond a certain point building the index pays off and it is worth the effort.