Was ist der effizienteste Weg, um alle DOM-Elemente in Java zu durchlaufen?
So etwas aber für jedes einzelne DOM-Element aktuell org.w3c.dom.Document
?
for(Node childNode = node.getFirstChild(); childNode!=null;){
Node nextChild = childNode.getNextSibling();
// Do something with childNode, including move or delete...
childNode = nextChild;
}
Document
, aber keine der Antworten führte zu Effizienzprüfungen, und die einzige Erwähnung der Effizienz war "Ich denke" oder ähnliche Vermutungen.Antworten:
Grundsätzlich haben Sie zwei Möglichkeiten, alle Elemente zu durchlaufen:
1. Rekursion verwenden (die häufigste Art, wie ich denke):
public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, TransformerException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document document = docBuilder.parse(new File("document.xml")); doSomething(document.getDocumentElement()); } public static void doSomething(Node node) { // do something with the current node instead of System.out System.out.println(node.getNodeName()); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node currentNode = nodeList.item(i); if (currentNode.getNodeType() == Node.ELEMENT_NODE) { //calls this method for all the children which is Element doSomething(currentNode); } } }
2. Vermeiden Sie eine Rekursion mit der
getElementsByTagName()
Methode*
als Parameter:public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, TransformerException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document document = docBuilder.parse(new File("document.xml")); NodeList nodeList = document.getElementsByTagName("*"); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { // do something with the current element System.out.println(node.getNodeName()); } } }
Ich denke, diese Wege sind beide effizient.
Hoffe das hilft.
quelle
NodeList
Optimierung von sequentiellen Aufrufen eine Art verzögerte Auswertung verborgenitem
?for (int i = 0; i < nodeList.getLength(); i++)
ändern
for (int i = 0, len = nodeList.getLength(); i < len; i++)
effizienter sein.
Die zweite Art der Javanna-Antwort ist möglicherweise die beste, da sie tendenziell ein flacheres, vorhersehbares Speichermodell verwendet.
quelle
Ich bin kürzlich auch über dieses Problem gestolpert. Hier ist meine Lösung. Ich wollte eine Rekursion vermeiden, also habe ich eine while-Schleife verwendet.
Aufgrund des Hinzufügens und Entfernens an beliebigen Stellen in der Liste habe ich mich für die
LinkedList
Implementierung entschieden./* traverses tree starting with given node */ private static List<Node> traverse(Node n) { return traverse(Arrays.asList(n)); } /* traverses tree starting with given nodes */ private static List<Node> traverse(List<Node> nodes) { List<Node> open = new LinkedList<Node>(nodes); List<Node> visited = new LinkedList<Node>(); ListIterator<Node> it = open.listIterator(); while (it.hasNext() || it.hasPrevious()) { Node unvisited; if (it.hasNext()) unvisited = it.next(); else unvisited = it.previous(); it.remove(); List<Node> children = getChildren(unvisited); for (Node child : children) it.add(child); visited.add(unvisited); } return visited; } private static List<Node> getChildren(Node n) { List<Node> children = asList(n.getChildNodes()); Iterator<Node> it = children.iterator(); while (it.hasNext()) if (it.next().getNodeType() != Node.ELEMENT_NODE) it.remove(); return children; } private static List<Node> asList(NodeList nodes) { List<Node> list = new ArrayList<Node>(nodes.getLength()); for (int i = 0, l = nodes.getLength(); i < l; i++) list.add(nodes.item(i)); return list; }
quelle