java NamedNodeMap 的通用 foreach 迭代

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4171380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 05:10:04  来源:igfitidea点击:

generic foreach iteration of NamedNodeMap

javaxmliterationgenericsw3c

提问by Thufir

In Java, looking at the NamedNodeMapinterface, how do you iterate it with generics? It seems to use Node rather than String, but I'm not so sure how to use Node objects...

在 Java 中,查看NamedNodeMap接口,如何使用泛型对其进行迭代?它似乎使用 Node 而不是 String,但我不太确定如何使用 Node 对象......

NamedNodeMap namedNodeMap = doc.getAttributes();
Map<String, String> stringMap = (Map<String, String>) namedNodeMap;
for (Map.Entry<String, String> entry : stringMap.entrySet()) {
  //key,value stuff here
}

Yes, I can see how to iterate without using generics and with a regular for loop, but I'd like to use the above ?idiom? for maps. Of course, the problem would appear to be that, despite the name, NamedNodeMap doesn't actually implement the Map interface! :(

是的,我可以看到如何在不使用泛型和常规 for 循环的情况下进行迭代,但我想使用上面的?成语?对于地图。当然,问题似乎是,尽管名称如此,NamedNodeMap 实际上并没有实现 Map 接口!:(

Guess you just gotta bite the bullet here and do something like:

猜猜你只需要在这里硬着头皮做一些事情:

/*
 * Iterates through the node attribute map, else we need to specify specific 
 * attribute values to pull and they could be of an unknown type
 */
private void iterate(NamedNodeMap attributesList) {
    for (int j = 0; j < attributesList.getLength(); j++) {
        System.out.println("Attribute: "
                + attributesList.item(j).getNodeName() + " = "
                + attributesList.item(j).getNodeValue());
    }
}

there's nothing nicer?

没有比这更好的了吗?

采纳答案by Stephen C

I don't think there is a nicer way to use those APIs. (Update: OK - maybe https://stackoverflow.com/a/28626556/139985counts as nice.)

我认为没有更好的方法来使用这些 API。(更新:好的 - 也许https://stackoverflow.com/a/28626556/139985 也算不错。)

Bear in mind that the W3C DOM Java APIs were specified before Java had generics or the new forsyntax, or even the Iteratorinterface. Also bear in mind that the W3C DOM APIs for Java are actually the result of mapping an IDL specification to Java.

请记住,W3C DOM Java API 是在 Java 具有泛型或新for语法,甚至Iterator接口之前指定的。还要记住,用于 Java 的 W3C DOM API 实际上是将 IDL 规范映射到 Java 的结果。

If you want nicer APIs for manipulating XML, etc in memory, maybe you should look at JDOM.

如果您想要更好的 API 来在内存中操作 XML 等,也许您应该看看 JDOM。

回答by Paolo Fulgoni

You can create your own Iterablewrapper for NamedNodeMapand then use it in a foreachloop.

您可以创建自己的Iterable包装器NamedNodeMap,然后在foreach循环中使用它。

For example, this could be a simple implementation:

例如,这可能是一个简单的实现:

public final class NamedNodeMapIterable implements Iterable<Node> {

    private final NamedNodeMap namedNodeMap;

    private NamedNodeMapIterable(NamedNodeMap namedNodeMap) {
        this.namedNodeMap = namedNodeMap;
    }

    public static NamedNodeMapIterable of(NamedNodeMap namedNodeMap) {
        return new NamedNodeMapIterable(namedNodeMap);
    }

    private class NamedNodeMapIterator implements Iterator<Node> {

        private int nextIndex = 0;

        @Override
        public boolean hasNext() {
            return (namedNodeMap.getLength() > nextIndex);
        }
        @Override
        public Node next() {
            Node item = namedNodeMap.item(nextIndex);
            nextIndex = nextIndex + 1;
            return item;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

    }

    @Override
    public Iterator<Node> iterator() {
        return new NamedNodeMapIterator();
    }
}

In this case, this would be the usage:

在这种情况下,这将是用法:

private void iterate(NamedNodeMap attributesList) {
    for (Node node : NamedNodeMapIterable.of(attributesList)) {
        System.out.println("Attribute: "
                + node.getNodeName() + " = " + node.getNodeValue());
    }
}

With a similar approach you could create an Iterableover Map.Entry<String, String>instances.

使用类似的方法,您可以创建一个IterableoverMap.Entry<String, String>实例。

回答by Charles Follet

As you can't cast NamedNodeMapto a Map, I suggest to loop using a classic for loop like that :

由于您不能将NamedNodeMap转换为Map,我建议使用经典的 for 循环来循环:

int numAttrs = namedNodeMap.getLength();
System.out.println("Attributes:");
for (int i = 0; i < numAttrs; i++){
   Attr attr = (Attr) pParameterNode.getAttributes().item(i);
   String attrName = attr.getNodeName();
   String attrValue = attr.getNodeValue();
   System.out.println("\t[" + attrName + "]=" + attrValue);
}

回答by Michel

From Java 8 solution:

从 Java 8 解决方案:

private static Iterable<Node> iterableNamedNodeMap(final NamedNodeMap namedNodeMap) {
    return () -> new Iterator<Node>() {

        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < namedNodeMap.getLength();
        }

        @Override
        public Node next() {
            if (!hasNext())
                throw new NoSuchElementException();
            return namedNodeMap.item(index++);
        }
    };
}