借助流和lambda将迭代解决方案转化为功能

时间:2016-10-17 11:39:43

标签: java dom

大家好我有以下代码与xml文件通信,找到给定用户的名称,然后更新他的令牌值。

XML:

<app>
    <user>
        <name>Rick Alacidhbccgga Bushaksen</name>
        <email>januszcebula@uu1.ovh</email>
        <password>januszek</password>
        <accessToken>666666666</accessToken>
        <description>User has profile photo only</description>
    </user>
    <user>
        <name>Rick Alacidhbccgga Bushaksen</name>
        <email>brajanfajny@uu1.ovh</email>
        <password>brajan123</password>
        <accessToken>bbb</accessToken>
        <description>User doesn not have any photos</description>
    </user>
    <user>
        <name>Rick Alacidhbccgga Bushaksen</name>
        <email>annesmith@uu1.ovh</email>
        <password>ania123</password>
        <accessToken>bbb</accessToken>
        <description>User has profile and other photos</description>
    </user>
</app>

这是我执行上述操作的方法:

public static void updateAccessTokenFunctional(FacebookTestUserAccount testUser) {
        final String userName = getNameOfTestUser(testUser);
        final String tokenValue = testUser.accessToken();
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(XML_FILE_NAME);

            Node company = doc.getFirstChild();

            for (int j = 0; j < doc.getElementsByTagName("user").getLength(); j++) {
                Node user = doc.getElementsByTagName("user").item(j);

                NodeList listOfChildNodes = user.getChildNodes();
                String currentNameOfUser = "";
                for (int i = 0; i < listOfChildNodes.getLength(); i++) {
                    Node node = listOfChildNodes.item(i);

                    if ("name".equals(node.getNodeName()))
                        currentNameOfUser = node.getTextContent();

                    if (currentNameOfUser.equals(userName) && "accessToken".equals(node.getNodeName())) {
                        node.setTextContent(tokenValue);
                    }
                }
            }
            // saving content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File(XML_FILE_NAME));
            transformer.transform(source, result);

        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (TransformerException tfe) {
            tfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (SAXException sae) {
            sae.printStackTrace();
        }
    }

    private static String getNameOfTestUser(FacebookTestUserAccount user) {
        String[] arr = user.getUserDetails().split("\"");
        return arr[3];
    }

它工作正常,但我想将其重构为功能解决方案(如果可能的话),这是我寻求帮助的部分。我尝试过像

这样的东西
 Stream.of(listOfChildNodes).///?

但是我无法映射它以获得单个节点...

1 个答案:

答案 0 :(得分:1)

没有直接的方法可以将NodeList或类似的内容转换为流。但是你可以通过IntStream间接地做到这一点。您可以编写帮助程序将NodeList转换为如下所示的流:

Stream<Node> toStream(NodeList nodeList) {
    return IntStream
            .range(0, nodeList.getLength())
            .mapToObj(nodeList::item);
}

然后得到例如XML中的所有用户名都可以执行此操作:

Stream<Node> userNodes = toStream(doc.getElementsByTagName("user"));

List<String> userNames = userNodes
        .flatMap(node -> toStream(node.getChildNodes())
                .filter(n -> n.getNodeName().equals("name")))
        .map(Node::getTextContent)
        .collect(Collectors.toList());

操作时要小心操作节点列表(删除,添加节点),因为这可能会导致意外结果。

相关问题