NamedNodeMap 的通用 foreach 迭代

发布于 2024-10-02 00:09:09 字数 1058 浏览 3 评论 0原文

在 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
}

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

我猜你必须硬着头皮做一些类似的事情:

/*
 * 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());
    }
}

没有什么比这更好的了?

In Java, looking at the NamedNodeMap interface, 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...

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! :(

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

隔纱相望 2024-10-09 00:09:09

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

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

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();
    }
}

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

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

使用类似的方法,您可以通过 Map.Entry 创建一个 Iterable 。代码>实例。

You can create your own Iterable wrapper for NamedNodeMap and then use it in a foreach loop.

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 Iterable over Map.Entry<String, String> instances.

岁月静好 2024-10-09 00:09:09

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

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

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

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

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

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

一身软味 2024-10-09 00:09:09

因为您无法投射 NamedNodeMapMap,我建议循环使用像这样的经典 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);
}

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

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);
}
属性 2024-10-09 00:09:09

来自 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++);
        }
    };
}

From Java 8 solution:

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++);
        }
    };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文