Java 在HashMap中反转键值对
我的数据结构如下:Java 在HashMap中反转键值对,java,arraylist,hashmap,Java,Arraylist,Hashmap,我的数据结构如下: Map<String,ArrayList<String>> graph = new HashMap<String,ArrayList<String>>(); private Map<String,ArrayList<String>> reverseAdjList(Map<String,ArrayList<String>> adjList){ Map<String,A
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;
}
Map-graph=newhashmap();
这本质上是一个哈希映射,它将字符串值作为键,并将字符串数组列表存储在键的值中。
现在,我尝试反转键值模式,使value成为键,并使key成为值。我的做法如下:
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;
}
private Map reverseAdjList(映射调整列表){
Map tGraph=newhashmap();
对于(Map.Entry:adjList.entrySet()){
String key=entry.getKey();
ArrayList值=新的ArrayList();
值。添加(键);
ArrayList值=entry.getValue();
for(字符串v:值){
if(t图容器(v)){
values.addAll(tGraph.get(v));
}
tGraph.put(v,值);
}
}
返回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)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间
位于java.util.Arrays.copyOf(Arrays.java:3210)
位于java.util.Arrays.copyOf(Arrays.java:3181)
在java.util.ArrayList.grow(ArrayList.java:261)
在java.util.ArrayList.ensureExplicitCapacity处(ArrayList.java:235)
位于java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
在java.util.ArrayList.addAll(ArrayList.java:579)
在GraphProcessor.reverseAdjList(GraphProcessor.java:67)
在GraphProcessor.SCC(GraphProcessor.java:135)
在GraphProcessor上。(GraphProcessor.java:50)
位于GraphProcessor.main(GraphProcessor.java:250)
我知道这是一种非常幼稚和错误的做法,什么是更好和正确的做法 您的代码中有一个错误:
for (Map.Entry<String, ArrayList<String>> entry : adjList.entrySet()) {
String key = entry.getKey();
ArrayList<String> values = new ArrayList<>(); // Wrong place for this variable.
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);
}
}
但实际上,您不需要为每个内部步骤创建新的列表实例。对于步骤,请使用JDK 1.8尝试以下代码:
private Map<String, List<String>> reverseMap(Map<String, List<String>> adjList) {
Map<String, List<String>> tGraph = new HashMap<>();
for (Map.Entry<String, List<String>> entry : adjList.entrySet()) {
for (String value : entry.getValue()) {
tGraph.computeIfAbsent(value, v -> new ArrayList<>()).add(entry.getKey()); // Updated according comment from @shmosel
}
}
return tGraph;
}
私有映射反向映射(映射调整列表){
Map tGraph=newhashmap();
对于(Map.Entry:adjList.entrySet()){
for(字符串值:entry.getValue()){
tGraph.computeIfAbsent(value,v->new ArrayList()).add(entry.getKey());//根据@shmosel的注释更新
}
}
返回tGraph;
}
如果您使用的是较旧版本的jdk,可以尝试:
private Map<String, List<String>> reverseMap(Map<String, List<String>> adjList) {
Map<String, List<String>> tGraph = new HashMap<>();
for (Map.Entry<String, List<String>> entry : adjList.entrySet()) {
for (String value : entry.getValue()) {
List<String> newValues = tGraph.get(value);
if (newValues == null) {
newValues = new ArrayList<>();
tGraph.put(value, newValues);
}
newValues.add(entry.getKey());
}
}
return tGraph;
}
私有映射反向映射(映射调整列表){
Map tGraph=newhashmap();
对于(Map.Entry:adjList.entrySet()){
for(字符串值:entry.getValue()){
List newValues=tGraph.get(值);
if(newValues==null){
newValues=newarraylist();
tGraph.put(值,newValues);
}
newValues.add(entry.getKey());
}
}
返回tGraph;
}
希望这能有所帮助:-)您的数据集有多大?也许您只需要使用-Xmx
增加jvm堆大小,因为您的代码是错误的<代码>值
对于每个键只实例化一次,并且对于每个值它都以指数形式增长。尝试移动ArrayList value=new ArrayList()
到内部进行循环。更好的是,将键添加到先前映射的列表中,而不是每次都复制。太棒了!非常感谢你把它修好了。还感谢您建议使用密钥。很抱歉,我通过尝试您的代码发现了您的错误,并将其作为答案发布,但shmosel对此进行了评论,答案中还包含一些重构想法,因此我决定保留它,希望它能有所帮助。没问题,我非常感谢您尝试帮助我@shizhz。非常感谢你,我发现你的回答很有帮助,而且解释得很好。非常感谢!这非常有帮助。@smriti非常乐意帮助:-)Java 8中更好的解决方案:tGraph.computeifassent(value,v->new ArrayList()).add(entry.getKey())代码>@shmosel,这真的很酷,非常感谢。我已经更新了答案:)