如何将 org.w3c.dom.NodeList 与 Java 8 Stream API 一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23360278/
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
How to use org.w3c.dom.NodeList with Java 8 Stream API?
提问by oschlueter
I believe the Interface org.w3c.dom.NodeListis missing a stream()
function to make use of the benefits of Java 8's Stream API. Considering the introduction of default methods to ensure backwards compatibility, I fail to understand why this Interface doesn't have stream()
function.
我相信接口org.w3c.dom.NodeList缺少一个stream()
函数来利用 Java 8 的 Stream API 的好处。考虑到引入了默认方法来确保向后兼容,我无法理解为什么这个接口没有stream()
功能。
So my questions are:
所以我的问题是:
- How do I use a
NodeList
in combination with the Stream API? - If it's discouraged to do so, what are the reasons for that?
- 如何将 a
NodeList
与 Stream API 结合使用? - 如果不鼓励这样做,原因是什么?
Thanks in advance!
提前致谢!
Edit: I'm currently using this utility wrapper:
编辑:我目前正在使用这个实用程序包装器:
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();
}
采纳答案by Ian Roberts
The DOM is a strange beast, the API is defined in a language-independent way by the W3C and then mapped into various different programming languages, so Java can't add anything Java-specific to the core DOM interfaces that wasn't part of the DOM spec in the first place.
DOM 是一头奇怪的野兽,API 是由 W3C 以一种独立于语言的方式定义的,然后映射到各种不同的编程语言中,因此 Java 无法向核心 DOM 接口添加任何 Java 特定的内容,这些内容不属于首先是 DOM 规范。
So while you can't use a NodeList
asa stream, you can easily create a stream froma NodeList
, using e.g.
因此,虽然您不能使用 aNodeList
作为流,但您可以轻松地从a创建流NodeList
,例如使用
Stream<Node> nodeStream = IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item);
However, there is one big caveat - a DOM NodeList
is live, and reflects changes to the original DOM tree since the list was created. If you add or remove elements in the DOM tree they may magically appear or disappear from existing NodeLists, and this may cause strange effects if this happens mid-iteration. If you want a "dead" node list you'll need to copy it into an array or list, as you are doing already.
但是,有一个很大的警告 - DOMNodeList
是live 的,它反映了自创建列表以来对原始 DOM 树的更改。如果在 DOM 树中添加或删除元素,它们可能会神奇地从现有的 NodeList 中出现或消失,如果在迭代中发生这种情况,这可能会导致奇怪的效果。如果你想要一个“死”节点列表,你需要将它复制到一个数组或列表中,就像你已经在做的那样。
回答by Stephen C
Considering the introduction of default methods to ensure backwards compatibility, I fail to understand why this Interface doesn't have stream() function.
考虑到引入默认方法以确保向后兼容,我无法理解为什么这个接口没有 stream() 函数。
The interface was defined before Java 8 existed. Since Stream
did not exist prior Java 8, it follows that NodeList
could notsupport it.
该接口是在 Java 8 出现之前定义的。由于Stream
在 Java 8 之前不存在,因此NodeList
无法支持它。
How do I use a NodeList in combination with the Stream API?
如何将 NodeList 与 Stream API 结合使用?
You can't. At least, not directly.
你不能。至少,不是直接的。
If it's discouraged to do so, what are the reasons for that?
如果不鼓励这样做,原因是什么?
It is not "discouraged". Rather it is not supported.
这不是“气馁”。相反,它不受支持。
The primary reason is history. See above.
主要原因是历史。看上面。
It is possible that the people responsible for specifying the org.w3c.dom
APIs for Java (i.e. the W3 consortium) will bring out a new edition of the APIs that will be more friendly to Java 8. However, that would introduce a bunch of new compatibility issues. The new edition of the APIs would would not be binary compatibility with the current ones, and would not be compatible with pre-Java 8 JVMs.
负责为org.w3c.dom
Java指定API 的人员(即 W3 联盟)可能会推出对 Java 8 更友好的新版 API。然而,这会引入一系列新的兼容性问题。新版本的 API 不会与当前的二进制兼容,也不会与 Java 8 之前的 JVM 兼容。
However, it is more complicated than just getting the W3 Consortium to update the APIs.
然而,这比让 W3 联盟更新 API 更复杂。
The DOM APIs are defined in CORBA IDL, and the Java APIs are "generated" by applying the CORBA Java mapping to the IDL. This mapping is specified by the OMG ... not the W3 Consortium. So creating a "Java 8 Stream friendly" version of the org.w3c.dom
APIs would entail either getting the OMG to update the CORBA Java mapping to be Stream
aware (which would be problematic from a CORBA compatibility perspective, at least) or breaking the connection between the Java API and CORBA.
DOM API 是在 CORBA IDL 中定义的,而 Java API 是通过将 CORBA Java 映射应用到 IDL 来“生成”的。这个映射是由 OMG 指定的……而不是 W3 联盟。因此,创建org.w3c.dom
API的“Java 8 Stream 友好”版本将需要让 OMG 更新 CORBA Java 映射以使其Stream
意识到(至少从 CORBA 兼容性角度来看这将是有问题的)或断开 Java API 之间的连接和 CORBA。
Unfortunately, finding out what (if anything) is happening in the OMG world on refreshing the IDL to Java mapping is difficult ... unless you work for an OMG member organization, etcetera. I don't.
不幸的是,在刷新 IDL 到 Java 的映射时,很难找出 OMG 世界中正在发生的事情(如果有的话)……除非您为 OMG 成员组织等工作。我不。
回答by serup
Here is an example where stream is used for finding a specific NodeList element :
这是一个使用流查找特定 NodeList 元素的示例:
private String elementOfInterest; // id of element
private String elementOfInterestValue; // value of element
public boolean searchForElementOfInterest(Document doc)
{
boolean bFound=false;
NodeList nList = doc.getElementsByTagName("entity");
// since NodeList does not have stream implemented, then use this hack
Stream<Node> nodeStream = IntStream.range(0, nList.getLength()).mapToObj(nList::item);
// search for element of interest in the NodeList
if(nodeStream.parallel().filter(this::isElementOfInterest).collect(Collectors.toList()).size() > 0)
bFound=true;
return bFound;
}
private boolean isElementOfInterest(Node nNode)
{
boolean bFound=false;
assert(nNode != null);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
String id = eElement.getElementsByTagName("id").item(0).getTextContent();
String data = eElement.getElementsByTagName("data").item(0).getTextContent();
if (id.contentEquals(elementOfInterest) && data.contentEquals(elementOfInterestValue))
bFound = true;
}
return bFound;
}
回答by armagedescu
java8 Stream.iterate
Use like that:
java8 Stream.iterate
像这样使用:
Stream.iterate(0, i -> i + 1)
.limit (nodeList.getLength())
.map (nodeList::item).forEach...