Here's the problem:
public static <T> T execute(String query, Function<List<JsonNode>, T> function) {
String jsonString = HttpRequest.get("http://overpass-api.de/api/interpreter", true, "data", query).body();
List<JsonNode> list = toJsonNodeList(jsonString);
T res = function.apply(list);
return res;
}
This method:
- perform a query that returns a json string
- transform that string into a JsonNode list
- finally, transform each JsonNode into a particular object
This is an example of function that convert each JsonNode into a geojson geometry and returns a geojson result set:
public class GeojsonMapper implements Function<List<JsonNode>, GeojsonSingleListResultSet> {
@Override
public GeojsonSingleListResultSet apply(List<JsonNode> list) {
List<Element> elementList = list.parallelStream()
.map(jsonNode -> {
String id = jsonNode.get("id").asText();
JsonNode tags = jsonNode.get("tags");
switch (jsonNode.get("type").asText()) {
case "node":
return new Point(jsonNode.get("lat").asDouble(), jsonNode.get("lon").asDouble(), id, tags);
case "way":
ArrayList<Point> points = new ArrayList<>();
JsonNode nodeList = jsonNode.get("geometry");
for (int j = 0; j < nodeList.size(); j++) {
JsonNode wayNode = nodeList.get(j);
points.add(j, new Point(wayNode.get("lat").asDouble(), wayNode.get("lon").asDouble()));
}
if (Polygon.isPolygon(points, tags)) {
return new Polygon(points, id, tags);
} else {
return new LineString(points, id, tags);
}
default:
Iterator<JsonNode> iterator = jsonNode.get("members").getElements();
List<List<Point>> rings = new ArrayList<>();
List<Point> ring = null;
while (iterator.hasNext()) {
JsonNode member = iterator.next();
JsonNode geometry = member.get("geometry");
ring = new ArrayList<>();
for (int ringIndex = 0; ringIndex < geometry.size(); ringIndex++) {
JsonNode coordinates = geometry.get(ringIndex);
ring.add(new Point(coordinates.get("lat").asDouble(), coordinates.get("lon").asDouble()));
}
rings.add(ring);
}
return new Multipolygon(Polygon.buildPolygons(rings), id, tags);
}
})
.collect(toList());
return new GeojsonSingleListResultSet(elementList);
}
}
Everything works well, but the toJsonNodeList() method is very slow in comparison to the method function.apply() that use a Stream. This is the toJsonNodeList()'s code:
private static List<JsonNode> toJsonNodeList(String s){
ObjectMapper mapper = new ObjectMapper();
List<JsonNode> list = new ArrayList<>();
try{
JsonNode resultSet = mapper.readTree(s).get("elements");
Iterator<JsonNode> iterator = resultSet.getElements();
while (iterator.hasNext()) {
list.add(iterator.next());
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
Is there a way to parse a json string using a parallelStream so as to extract each element and convert it to a JsonNode?