繁体   English   中英

如何比较两个HashMap <String, List<String> &gt; 以列表项作为值来检查 hMap1 中的值是否存在于 hMap2 中

[英]How to compare two HashMap<String, List<String>> with list items as values to check if value in hMap1 is present in hMap2

我有两个单独的地图,以项目列表作为值。 我正在从两个单独的 xml 文件中读取数据来填充这些地图。 地图的内容如下所示:

    Map<String,List<String>> hMap1 = new HashMap<>();
    Map<String,List<String>> hMap2 = new HashMap<>();

    hmAP1   key:Bob val[aa,bb,cc,dd,ee]
            key:Sam val[ss,tt,uu,vv,ww]

    hMap2   key:Dan val[xx,pp,yy,qq,zz]
            key:Bob val[cc,dd,hh,kk,mm]

我想比较 hMap1 和 hMap2 中的值。 在这种情况下,hMap1 [cc, dd] 中的 Bob 具有与 hMap2 [cc, dd] 中的 Bob 相似的值。 如何仅将 Bob 和匹配值添加到新的 hMap3。 拜托了,我似乎无法理解。 这是我阅读 xml 文件并添加到 hashMaps 的过程:

 public static Map<String,List<String>> checkSimilarValues (File file) throws TransformerException, ParserConfigurationException, SAXException, IOException
    {

        Map<String, List<String>> hMap = new HashMap<>();

        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc1 = dBuilder.parse(file);
       // System.out.println(file.getName());
        doc1.getDocumentElement().normalize();

        NodeList nList = doc1.getElementsByTagName("class");

        for (int temp = 0; temp < nList.getLength(); temp++) {
            Node nNode = nList.item(temp);

            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                Element eElement = (Element) nNode;

                // list of include methods
                NodeList includeMethods = eElement.getElementsByTagName("include");

                for (int count = 0; count < includeMethods.getLength(); count++) {
                    Node node1 = includeMethods.item(count);

                    if (node1.getNodeType() == node1.ELEMENT_NODE) {
                        Element methods = (Element) node1;

                        List<String> current = 
                      hMap.get(eElement.getAttribute("name"));

                       // List<String> current2 = 
                      map.get(eElement.getAttribute("name"));
                        if (current == null) {
                            current = new ArrayList<String>();
                            hMap.put(eElement.getAttribute("name"), current);
                        }
                       if (!(current.contains(methods.getAttribute("name")))) {
                            current.add(methods.getAttribute("name"));

                        }

                    }
                } 
            }

        }
        return hMap; 

    }

     public static void main (String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerException
    {
        File f1 = new File("sample1.xml");
        File f2 = new File("sample2.xml");

        Map<String, List<String>> hMap1 = new HashMap<>();
        Map<String, List<String>> hMap2 = new HashMap<>();

        hMap1 = checkSimilarValues(f1);
        hMap2 = checkSimilarValues(f2);

        for (String key : hMap1.keySet()) {
            System.out.println(key);

            for (String string : hMap1.get(key)) {
                System.out.println(string);

            }
        }

    }

样本1.xml

<classes>
<class name="Bob">
    <methods>
        <include name="cc" />
        <include name="cc" />
        <include name="hh" />
        <include name="kk" />
        <include name="mm" />
    </methods>
</class>
<class name="Dan">
    <methods>
        <include name="xx" />
        <include name="pp" />
        <include name="yy" />
        <include name="qq" />
        <include name="zz" />
    </methods>
</class>

样本2.xml

<classes>
<class name="Bob">
    <methods>
        <include name="aa" />
        <include name="bb" />
        <include name="cc" />
        <include name="dd" />
        <include name="ee" />
    </methods>
</class>
<class name="Sam">
    <methods>
        <include name="ss" />
        <include name="tt" />
        <include name="uu" />
        <include name="vv" />
        <include name="ww" />
    </methods>
</class>

使用 XSLT(2.0 或更高版本)在 XML 级别执行此操作比在 Java 级别执行要容易得多。 例如,您可以创建一个文档来合并使用提供的两个输入

<xsl:variable name="inputs" select="doc('sample1.xml'), doc('sample2.xml')"/>

<xsl:template name="main">
  <classes>
    <xsl:for-each-group select="$inputs//class" group-by="@name">
      <methods>
        <xsl:for-each select="distinct-values(current-group()/methods/include/@name">
          <include name="{.}"/>
        </xsl:for-each>
      </methods>
    </xsl:for-each-group>
  </classes>
</xsl:template>

这为您提供了每个名称的所有“包含”元素的联合 - 我不确定这是否正是您所要求的。 如果您对要解决的问题进行高层次的描述,而不是用 Java 哈希表的操作来表达它,那会更容易。

你可以试试这个:

Map<String, List<String>> resultMap = new HashMap<>();
for (String k: hMap1.keySet()) {
  if (!hMap2.containsKey(k)) continue;
  List<String> list = new ArrayList<>(hMap1.get(k));
  list.retainAll(hMap2.get(k));
  resultMap.put(k, list);
}

在 Java 8 中这很容易。您可以流式传输两个地图条目,过滤其键属于这两个地图的条目,并将这些条目收集到一个新地图中,通过将它们相交来合并值。 在代码中:

Map<String, List<String>> hMap3 = Stream.of(hMap1, hMap2)
    .flatMap(map -> map.entrySet().stream())
    .filter(e -> hMap1.containsKey(e.getKey()) && hMap2.containsKey(e.getKey()))
    .collect(Collectors.toMap(
             Map.Entry::getKey,
             e -> new ArrayList<>(e.getValue()),
             (l1, l2) -> { l1.retainAll(l2); return l1; }));

另一种可能性是迭代hMap1键,如果hMap2包含当前键,则将一个条目放入新映射中,将键映射到值的交集:

Map<String, List<String>> hMap3 = new HashMap<>();
hMap1.forEach((k1, v1) -> {
    List<String> v2 = hMap2.get(k1);
    if (v2 != null) {
        List<String> v3 = new ArrayList<>(v1);
        v3.retainAll(v2);
        hMap3.put(k1, v3);
    }
});

首先复制数据然后删除差异的变体:

Map<String, List<String>> hMap3 = new HashMap<>(hMap1);
hMap3.keys().retainAll(hMap2.keys());
hMap3.replaceAll((k, v) -> {
    List<String> v3 = new ArrayList<>(v);
    v3.retainAll(hMap2.get(k));
    return v3;
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM