如何将 org.w3c.dom.NodeList 与 Java 8 Stream API 配合使用?

2022-09-01 14:57:32

我相信Interface org.w3c.dom.NodeList缺少一个功能来利用Java 8的Stream API的好处。考虑到引入默认方法以确保向后兼容性,我无法理解为什么这个接口没有功能。stream()stream()

所以我的问题是:

  • 如何将 与流 API 结合使用?NodeList
  • 如果不鼓励这样做,那是什么原因呢?

提前致谢!

编辑:我目前正在使用此实用程序包装器:

private static Stream<Node> nodeStream(NodeList list) {
    List<Node> nodes = new ArrayList<>();

    for (int n = 0; n < list.getLength(); ++n) {
        nodes.add(list.item(n));
    }

    return nodes.stream();
}

答案 1

DOM是一个奇怪的野兽,API由W3C以一种与语言无关的方式定义,然后映射到各种不同的编程语言中,因此Java不能将任何特定于Java的东西添加到核心DOM接口中,而这些接口最初不是DOM规范的一部分。

因此,虽然您不能将 a 用作流,但您可以使用例如 轻松地 中创建流。NodeListNodeList

Stream<Node> nodeStream = IntStream.range(0, nodeList.getLength())
                                   .mapToObj(nodeList::item);

但是,有一个很大的警告 - DOM是实时的,并且反映了自创建列表以来对原始DOM树的更改。如果在 DOM 树中添加或删除元素,它们可能会神奇地出现或从现有 NodeList 中消失,如果这种情况发生在迭代过程中,这可能会产生奇怪的影响。如果你想要一个“死”节点列表,你需要把它复制到数组或列表中,就像你已经做的那样。NodeList


答案 2

考虑到引入默认方法以确保向后兼容性,我无法理解为什么这个接口没有stream()函数。

该接口是在 Java 8 存在之前定义的。由于在Java 8之前不存在,因此无法支持它。StreamNodeList

如何将 NodeList 与流 API 结合使用?

你不能。至少,不是直接的。

如果不鼓励这样做,那是什么原因呢?

它不是“气馁”的。相反,它不受支持。

主要原因是历史。见上文。

负责为Java指定API的人(即W3联盟)可能会推出对Java 8更友好的新版本API。但是,这将引入一堆新的兼容性问题。新版本的API不会与当前API的二进制兼容性,也不会与Java 8之前的JVM兼容。org.w3c.dom


但是,这比仅仅让 W3 联盟更新 API 要复杂得多。

DOM API 是在 CORBA IDL 中定义的,Java API 是通过将 CORBA Java 映射应用于 IDL 来“生成”的。此映射由 OMG 指定...而不是 W3 联盟。因此,创建API的“Java 8流友好”版本需要让OMG更新CORBA Java映射以进行感知(至少从CORBA兼容性的角度来看,这将是有问题的),或者断开Java API和CORBA之间的连接。org.w3c.domStream

不幸的是,找出OMG世界中在刷新IDL到Java映射时发生了什么(如果有的话)是很困难的......除非您为OMG成员组织等工作。我没有。