You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:24:29