【发布时间】:2017-03-30 01:44:33
【问题描述】:
我的数据结构如下:
Map<String,ArrayList<String>> graph = new HashMap<String,ArrayList<String>>();
这本质上是一个哈希映射,它将字符串值作为键并将字符串的数组列表存储在键的值中。 现在我正在尝试反转键值模式,使值成为键,键成为值。我的做法是这样的:
private Map<String,ArrayList<String>> reverseAdjList(Map<String,ArrayList<String>> adjList){
Map<String,ArrayList<String>> tGraph = new HashMap<String,ArrayList<String>>();
for (Map.Entry<String, ArrayList<String>> entry : adjList.entrySet()) {
String key = entry.getKey();
ArrayList<String> values = new ArrayList<>();
values.add(key);
ArrayList<String> value = entry.getValue();
for(String v:value){
if(tGraph.containsKey(v)){
values.addAll(tGraph.get(v));
}
tGraph.put(v, values);
}
}
return tGraph;
}
所以这对我来说可以反转小数据集的哈希映射键值模式但是当我在更大的数据集上尝试它时遇到了
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.addAll(ArrayList.java:579)
at GraphProcessor.reverseAdjList(GraphProcessor.java:67)
at GraphProcessor.SCC(GraphProcessor.java:135)
at GraphProcessor.<init>(GraphProcessor.java:50)
at GraphProcessor.main(GraphProcessor.java:250)
我知道这是一种非常幼稚和错误的做法,有什么更好和正确的做法呢?
【问题讨论】:
-
您的数据集有多大?也许您只需要使用
-Xmx增加您的 jvm 堆大小 -
您的代码错误。
values每个键仅实例化一次,并且每个值都呈指数增长。尝试将ArrayList<String> values = new ArrayList<>();移动到内部for循环。更好的是,将key添加到先前映射的列表中,而不是每次都复制。 -
太棒了!非常感谢你修复它。也感谢使用密钥的建议。
-
抱歉,我通过尝试您的代码并将其发布为答案发现了您的错误,但 shmosel 已对其进行了评论,答案中还有一些重构的想法,所以我决定保留它,希望对您有所帮助。
-
没问题,非常感谢您尝试帮助我@shizhz。非常感谢你,我发现你的回答真的很有帮助,而且解释得很好。