Can I iterate through a NodeList using for-each in Java?

前端 未结 10 1100
没有蜡笔的小新
没有蜡笔的小新 2020-12-09 00:55

I want to iterate through a NodeList using a for-each loop in Java. I have it working with a for loop and a do-while loop but not for-each.

Node         


        
相关标签:
10条回答
  • 2020-12-09 01:21

    I know it is late to the party, but...
    Since Java-8 you can write @RayHulha's solution even more concisely by using lambda expression (for creating a new Iterable) and default method (for Iterator.remove):

    public static Iterable<Node> iterable(final NodeList nodeList) {
        return () -> new Iterator<Node>() {
    
            private int index = 0;
    
            @Override
            public boolean hasNext() {
                return index < nodeList.getLength();
            }
    
            @Override
            public Node next() {
                if (!hasNext())
                    throw new NoSuchElementException();
                return nodeList.item(index++); 
            }
        };
    }
    

    and then use it like this:

    NodeList nodeList = ...;
    for (Node node : iterable(nodeList)) {
        // ....
    }
    

    or equivalently like this:

    NodeList nodeList = ...;
    iterable(nodeList).forEach(node -> {
        // ....
    });
    
    0 讨论(0)
  • 2020-12-09 01:21

    The validated solution is very useful, but here I share an improved solution based on the valid one, this helps you iterate as well, but easy to use, and secure:

    public class XMLHelper {
        private XMLHelper() { }
    
        public static List<Node> getChildNodes(NodeList l) {
            List<Node> children = Collections.<Node>emptyList();
            if (l != null && l.getLength() > 0) {
                if (l.item(0) != null && l.item(0).hasChildNodes()) {
                    children = new NodeListWrapper(l.item(0).getChildNodes());
                }
            }
            return children;
        }
    
        public static List<Node> getChildNodes(Node n) {
            List<Node> children = Collections.<Node>emptyList();
            if (n != null && n.hasChildNodes()) {
                NodeList l = n.getChildNodes();
                if (l != null && l.getLength() > 0) {
                    children = new NodeListWrapper(l);
                }
            }
            return children;
        }
    
        private 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();
            }
        }
    

    }

    Usage:

     for (Node inner : XMLHelper.getChildNodes(node)) { ... }
    

    Thanks @Holger.

    0 讨论(0)
  • 2020-12-09 01:23

    There are ready to use or copypaste iterator implementations in org.apache.commons.collections4.iterators.NodeListIterator and com.sun.xml.internal.ws.util.xml.NodeListIterator.

    0 讨论(0)
  • 2020-12-09 01:29
    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();
            }
          };
        }
      };
    }
    
    0 讨论(0)
  • 2020-12-09 01:30

    Adding the happy little kotlin version for sience:

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

    One can then use it with nodeList.forEach { do_something_awesome() }

    0 讨论(0)
  • 2020-12-09 01:31

    As NodeList is just an interface, you could create a class which would implement both NodeList and Iterable, in order to iterate through it.

    0 讨论(0)
提交回复
热议问题