Contents Prev: Hello World Next: Using tags: counting businesses

Iterators and readers: counting elements

In this example we will retrieve some data from the Overpass API using a bounding box query. We then iterate all objects in the returned dataset and count the number of nodes, ways and relations we encounter:

  public static void main(String[] args) throws IOException
  {
    // Define a query to retrieve some data
    String query = "http://www.overpass-api.de/api/xapi?*[bbox="
        + "13.465661,52.504055,13.469817,52.506204]";
 
    // Open a stream
    InputStream input = new URL(query).openStream();
 
    // Create an iterator for XML data
    OsmIterator iterator = new OsmXmlIterator(input, false);
 
    // Initialize some counters
    int numNodes = 0;
    int numWays = 0;
    int numRelations = 0;
 
    // Iterate elements and increment our counters
    // depending on the type of element
    for (EntityContainer container : iterator) {
      if (container.getType() == EntityType.Node) {
        numNodes++;
      } else if (container.getType() == EntityType.Way) {
        numWays++;
      } else if (container.getType() == EntityType.Relation) {
        numRelations++;
      }
    }
 
    // Print the results
    System.out.println("nodes: " + numNodes);
    System.out.println("ways: " + numWays);
    System.out.println("relations: " + numRelations);
  }

Here's the output:

nodes: 898
ways: 71
relations: 20

The OsmIterator extends the standard java.util.Iterator, hence you can also replace the for loop with a while loop if you prefer this style:

    while (iterator.hasNext()) {
      EntityContainer container = iterator.next();
      if (container.getType() == EntityType.Node) {
        numNodes++;
      } else if (container.getType() == EntityType.Way) {
        numWays++;
      } else if (container.getType() == EntityType.Relation) {
        numRelations++;
      }
    }

Using a reader instead of an iterator

The previous examples used the iterator pattern for accessing our data. As an alternative, osm4j provides OsmReader implementations for all data formats to support callback driven programming out of the box:

Here's a reimplementation of the element counter using callbacks. We define a Counter class that extends the DefaultOsmHandler so that it can be passed to the reader using the setHandler() method:

  public static void main(String[] args) throws IOException, OsmInputException
  {
    // Define a query to retrieve some data
    String query = "http://www.overpass-api.de/api/xapi?*[bbox="
        + "13.465661,52.504055,13.469817,52.506204]";
 
    // Open a stream
    InputStream input = new URL(query).openStream();
 
    // Create a reader for XML data
    OsmReader reader = new OsmXmlReader(input, false);
 
    // Create our counter and set it as a handler for the reader
    Counter counter = new Counter();
    reader.setHandler(counter);
 
    // Let the reader parse the data
    reader.read();
 
    // Print the results
    System.out.println("nodes: " + counter.numNodes);
    System.out.println("ways: " + counter.numWays);
    System.out.println("relations: " + counter.numRelations);
  }
 
  private static class Counter extends DefaultOsmHandler
  {
 
    int numNodes = 0;
    int numWays = 0;
    int numRelations = 0;
 
    @Override
    public void handle(OsmNode node)
    {
      numNodes++;
    }
 
    @Override
    public void handle(OsmWay way)
    {
      numWays++;
    }
 
    @Override
    public void handle(OsmRelation relation)
    {
      numRelations++;
    }
 
  }
Contents Prev: Hello World Next: Using tags: counting businesses