我有两个单独的地图,其中商品列表为值。我正在从两个单独的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);
}
}
}
sample1.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>
sample2.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>
答案 0 :(得分:1)
使用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>
这给您每个名称的所有“ include”元素的并集-我不确定这是否正是您要的。如果您对要解决的问题进行高级描述,而不是用对Java哈希表的操作来表述,将更加容易。
答案 1 :(得分:0)
您可以尝试以下方法:
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);
}
答案 2 :(得分:0)
在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;
});