我认为接口org.w3c.dom.NodeList缺少stream()
函数,以利用Java 8的Stream API的优势。考虑引入默认方法以确保向后兼容性,我无法理解为什么此接口没有stream()
功能。
所以我的问题是:
NodeList
与Stream API结合使用?提前致谢!
编辑:我目前正在使用此实用程序包装器:
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();
}
答案 0 :(得分:47)
DOM是一个奇怪的野兽,由W3C以与语言无关的方式定义API,然后映射到各种不同的编程语言,因此Java无法添加任何特定于Java的核心DOM接口。首先是DOM规范的一部分。
因此,虽然您无法将NodeList
用作流,但您可以使用例如<{1}}轻松地创建来自的流
NodeList
然而,有一个重要的警告 - DOM Stream<Node> nodeStream = IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item);
live ,并反映自创建列表以来对原始DOM树的更改。如果在DOM树中添加或删除元素,它们可能会从现有的NodeLists中神奇地出现或消失,如果在迭代中发生这种情况,这可能会导致奇怪的效果。如果你想要一个“死”节点列表,你需要将它复制到一个数组或列表中,就像你已经做的那样。
答案 1 :(得分:5)
考虑引入默认方法以确保向后兼容性,我无法理解为什么此接口没有stream()函数。
接口是在Java 8存在之前定义的。由于{8}之前不存在Stream
,因此NodeList
无法支持它。
如何将NodeList与Stream API结合使用?
你做不到。至少,不是直接。
如果不鼓励这样做,原因是什么?
不是“气馁”。相反,它不受支持。
主要原因是历史。见上文。
负责指定Java org.w3c.dom
API(即W3联盟)的人员可能会推出一个对Java 8更友好的新版API。但是,这将引入一堆新的兼容性问题。新版本的API不会与当前版本的二进制兼容,并且与Java 8之前的JVM不兼容。
然而,它比让W3联盟更新API更复杂。
DOM API在CORBA IDL中定义,并且通过将CORBA Java映射应用于IDL来“生成”Java API。此映射由OMG ...而不是W3 Consortium指定。因此,创建org.w3c.dom
API的“Java 8 Stream友好”版本需要让OMG更新CORBA Java映射以Stream
知道(从CORBA兼容性角度来看,这将是有问题的,在至少)或破坏Java API和CORBA之间的连接。
不幸的是,发现OMG世界中正在发生的关于刷新IDL到Java映射的内容(如果有的话)很难......除非您为OMG成员组织工作,等等。我没有。
答案 2 :(得分:1)
以下是使用stream查找特定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;
}
答案 3 :(得分:0)
java8 Stream.iterate
像这样使用:
Stream.iterate(0, i -> i + 1)
.limit (nodeList.getLength())
.map (nodeList::item).forEach...