OSM文件解析器的性能与可读性优化咨询(含自研与Java原生StAX两种实现)
OSM文件解析器的性能与可读性优化咨询(含自研与Java原生StAX两种实现)
我需要开发一个能解析OSM文件的解析器,现在纠结于怎么在性能和可读性上做优化。我写了两个版本的解析器:一个是自己手写的,另一个用了Java原生的XML解析器(StAX)。有没有大佬能帮我分析下怎么优化这两个实现呀?
万分感谢!
自研版本解析器
//HOMEMADE PARSER public class Parser implements IParser { private final String fileName; private final List<Double> boundingBox = new ArrayList<>(); private final HashMap<Long, OsmNode> osmNodeMap = new HashMap<>(); private final HashMap<Long, OsmWay> osmWayMap = new HashMap<>(); private final HashMap<Long, OsmRelation> osmRelationMap = new HashMap<>(); public Parser(String filename) { this.fileName = filename; } @Override public void parse() { try { InputStream is = Parser.class.getResourceAsStream("/data/" + fileName); BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); String line; while ((line = br.readLine()) != null) { //System.out.println(line); line=line.trim(); if (line.startsWith("<bounds")) { double minlat = getAttributeDouble(line, "minlat"); double minlon = getAttributeDouble(line, "minlon"); double maxlat = getAttributeDouble(line, "maxlat"); double maxlon = getAttributeDouble(line, "maxlon"); boundingBox.add(minlat); boundingBox.add(minlon); boundingBox.add(maxlat); boundingBox.add(maxlon); } if (line.startsWith("<node")) { long id = getAttributeLong(line, "id"); double lat = getAttributeDouble(line, "lat"); double lon = getAttributeDouble(line, "lon"); OsmNode osmNode = new OsmNode(id, lat, lon); osmNodeMap.put(id, osmNode); } if (line.startsWith("<way")) { long id = getAttributeLong(line, "id"); String subline; List<OsmNode> nodes = new ArrayList<>(); HashMap<String, String> tags = new HashMap<>(); while ((subline = br.readLine()) != null) { subline=subline.trim(); if (subline.startsWith("</way>")) { break; } if (subline.startsWith("<nd")) { long subid = getAttributeLong(subline, "ref"); OsmNode osmNode = osmNodeMap.get(subid); nodes.add(osmNode); } else if (subline.startsWith("<tag")) { String k = getAttribute(subline, "k"); String v = getAttribute(subline, "v"); tags.put(k, v); } } OsmWay osmWay = new OsmWay(id, nodes, tags); osmWayMap.put(id, osmWay); } if (line.startsWith("<relation")) { long id = getAttributeLong(line, "id"); OsmRelation currentRelation = osmRelationMap.get(id); if (currentRelation == null) { currentRelation = new OsmRelation(id, new ArrayList<>(), new HashMap<>()); osmRelationMap.put(id, currentRelation); } String subline; ArrayList<Member> members = new ArrayList<>(); HashMap<String, String> tags = new HashMap<>(); while ((subline = br.readLine()) != null) { subline=subline.trim(); if (subline.startsWith("</relation>")) { break; } if (subline.startsWith("<member")) { String type = getAttribute(subline, "type"); long refId = getAttributeLong(subline, "ref"); String role = getAttribute(subline, "role"); switch (type) { case "node": OsmNode node = osmNodeMap.get(refId); if (node != null) { members.add(new Member(node, role)); } break; case "way": OsmWay way = osmWayMap.get(refId); if (way != null) { members.add(new Member(way, role)); } break; case "relation": OsmRelation refRel = osmRelationMap.get(refId); if (refRel == null) { refRel = new OsmRelation(refId, new ArrayList<>(), new HashMap<>()); osmRelationMap.put(refId, refRel); } members.add(new Member(refRel, role)); break; default: break; } } if (subline.startsWith("<tag")) { String k = getAttribute(subline, "k"); String v = getAttribute(subline, "v"); tags.put(k, v); } } currentRelation.setMembers(members); currentRelation.setTags(tags); } } } catch (IOException e) { System.out.println(e.getMessage()); } } public String getAttribute(String s, String key) { String pattern = key + "=\""; int start = s.indexOf(pattern); if (start == -1) { return null; } int valueStart = start + pattern.length(); int valueEnd = s.indexOf('"', valueStart); return s.substring(valueStart, valueEnd); } public double getAttributeDouble(String s, String key) { String val = getAttribute(s, key); if (val == null) { return Double.NaN; } return Double.parseDouble(val); } public long getAttributeLong(String s, String key) { String val = getAttribute(s, key); if (val == null) { return 0L; } return Long.parseLong(val); } @Override public List<Double> getBoundingBox() { return boundingBox; } @Override public HashMap<Long, OsmNode> getOsmNodeMap() { return osmNodeMap; } @Override public HashMap<Long, OsmWay> getOsmWayMap() { return osmWayMap; } @Override public HashMap<Long, OsmRelation> getOsmRelationMap() { return osmRelationMap; } }
Java原生StAX版本解析器(注:代码存在截断)
//JAVAS OWN XML-PARSER public class ParserStax implements IParser { private final String fileName; private final List<Double> boundingBox = new ArrayList<>(); private final HashMap<Long, OsmNode> osmNodeMap = new HashMap<>(); private final HashMap<Long, OsmWay> osmWayMap = new HashMap<>(); private final HashMap<Long, OsmRelation> osmRelationMap = new HashMap<>(); public ParserStax(String filename) { this.fileName = filename; } @Override public void parse() { try (InputStream is = ParserStax.class.getResourceAsStream("/data/" + fileName)) { if (is == null) { throw new IllegalArgumentException("Resource not found: /data/" + fileName); } XMLInputFactory factory = XMLInputFactory.newInstance(); safeConfigure(factory); XMLStreamReader r = factory.createXMLStreamReader(is); Long currentWayId = null; List<OsmNode> currentWayNodes = null; HashMap<String, String> currentWayTags = null; Long currentRelId = null; ArrayList<Member> currentRelMembers = null; HashMap<String, String> currentRelTags = null; while (r.hasNext()) { int event = r.next(); if (event == XMLStreamConstants.START_ELEMENT) { String name = r.getLocalName(); switch (name) { case "bounds" -> { double minlat = getAttrDouble(r, "minlat"); double minlon = getAttrDouble(r, "minlon"); double maxlat = getAttrDouble(r, "maxlat"); double maxlon = getAttrDouble(r, "maxlon"); boundingBox.add(minlat); boundingBox.add(min
备注:内容来源于Stack Exchange,提问作者Theo Tärnberg
相关产品推荐
相关产品推荐

