我可以遍历一个NodeList使用for-each在Java中?

我想在Java中使用for-each循环遍历NodeList 。 我有一个for循环和一个do-while循环但不是for-each循环。

 NodeList nList = dom.getElementsByTagName("year"); do { Element ele = (Element) nList.item(i); list.add(ele.getElementsByTagName("MonthId").item(0).getTextContent()); i++; } while (i < nList.getLength()); NodeList nList = dom.getElementsByTagName("year"); for (int i = 0; i < nList.getLength(); i++) { Element ele = (Element) nList.item(i); list.add(ele.getElementsByTagName("MonthId").item(0).getTextContent()); } 

这个问题的解决方法是直截了当的,谢天谢地,你只需要实现一次。

 import java.util.*; import org.w3c.dom.*; public final class XmlUtil { private XmlUtil(){} public static List<Node> asList(NodeList n) { return n.getLength()==0? Collections.<Node>emptyList(): new NodeListWrapper(n); } static final class NodeListWrapper extends AbstractList<Node> implements RandomAccess { private final NodeList list; NodeListWrapper(NodeList l) { list=l; } public Node get(int index) { return list.item(index); } public int size() { return list.getLength(); } } } 

一旦将这个实用程序类添加到您的项目中,并将XmlUtil.asList方法的static import添加到源代码中,您可以像这样使用它:

 for(Node n: asList(dom.getElementsByTagName("year"))) { … } 

由于NodeList只是一个接口,您可以创建一个类来实现NodeListIterable ,以便遍历它。

 public static Iterable<Node> iterable(final NodeList n) { return new Iterable<Node>() { @Override public Iterator<Node> iterator() { return new Iterator<Node>() { int index = 0; @Override public boolean hasNext() { return index < n.getLength(); } @Override public Node next() { if (hasNext()) { return n.item(index++); } else { throw new NoSuchElementException(); } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } 

NodeList没有实现Iterable ,所以你不能在增强的for循环中使用它。

如果当前迭代NodeList(通过getElementsByTagName()和其他方法创建)当前DOM元素被删除(通过JavaScript),元素将从NodeList中消失。 这使得NodeList的正确迭代更加棘手。

 public class IteratableNodeList implements Iterable<Node> { final NodeList nodeList; public IteratableNodeList(final NodeList _nodeList) { nodeList = _nodeList; } @Override public Iterator<Node> iterator() { return new Iterator<Node>() { private int index = -1; private Node lastNode = null; private boolean isCurrentReplaced() { return lastNode != null && index < nodeList.getLength() && lastNode != nodeList.item(index); } @Override public boolean hasNext() { return index + 1 < nodeList.getLength() || isCurrentReplaced(); } @Override public Node next() { if (hasNext()) { if (isCurrentReplaced()) { // It got removed by a change in the DOM. lastNode = nodeList.item(index); } else { lastNode = nodeList.item(++index); } return lastNode; } else { throw new NoSuchElementException(); } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public Stream<Node> stream() { Spliterator<Node> spliterator = Spliterators.spliterator(iterator(), nodeList.getLength(), 0); return StreamSupport.stream(spliterator, false); } } 

然后像这样使用它: new IteratableNodeList(doc.getElementsByTagName(elementType)). stream().filter(...) new IteratableNodeList(doc.getElementsByTagName(elementType)). stream().filter(...)

或者: new IteratableNodeList(doc.getElementsByTagName(elementType)).forEach(...)

为科学添加快乐的小kotlin版本:

 fun NodeList.forEach(action: (Node) -> Unit) { (0 until this.length) .asSequence() .map { this.item(it) } .forEach { action(it) } } 

然后可以使用它与nodeList.forEach { do_something_awesome() }