我正在尝试创建一个邻接列表来存储图形。实现在存储100,000条记录时工作正常。但是,当我试图存储大约100万条记录时 我遇到了OutofMemory错误:
线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间 at java.util.Arrays.copyOfRange(Arrays.java:3209) 在java.lang.String。(String.java:215) 在java.io.BufferedReader.readLine(BufferedReader.java:331) 在java.io.BufferedReader.readLine(BufferedReader.java:362) 在liarliar.main(liarliar.java:39)
以下是我的实施
HashMap<String,ArrayList<String>> adj = new HashMap<String,ArrayList<String>>(num);
while ((str = in.readLine()) != null)
{
StringTokenizer Tok = new StringTokenizer(str);
name = (String) Tok.nextElement();
cnt = Integer.valueOf(Tok.nextToken());
ArrayList<String> templist = new ArrayList<String>(cnt);
while(cnt>0)
{
templist.add(in.readLine());
cnt--;
}
adj.put(name,templist);
} //done creating a adjacency list
我想知道,如果有更好的方法来实现邻接列表。此外,我知道开始时的节点数量,并且在将来我访问节点时将列表展平。有什么建议吗?
由于
答案 0 :(得分:1)
我似乎在这里有不公平的优势,因为我认识到问题的名称(liarliar
)和输入的确切性质。
我可以告诉你,这个OutOfMemoryError
是设计的。您需要找到一个更好的算法,它不会将图形的整个邻接信息存储在内存中。
我将避免提供过多的算法洞察力,但我可以告诉你,你需要坐下来思考,而不是在这个阶段进行编程。也许读一本关于算法和数据结构的好书。
您现在正在做的是,您实际上将输入文件中的字符串存储在HashMap<String,ArrayList<String>>
中。考虑到问题的本质,这是非常低效的。
如果您使用java.util.Scanner
,则更容易,效率更高。 <{1}}和new Scanner(new File(inputFilename))
以及next()
就是您所需要的一切。
为每个名称指定一个唯一的nextInt()
(提示:int
),然后存储更小的Map<String, Integer>
。
答案 1 :(得分:0)
感谢您回答我的问题。是的,你猜对了,代码是关于什么的。
我想是的,使用字符串到整数的映射会为邻居列表节省一些空间请求。从这个意义上讲,可以消除上述错误。
但是,我使用了java -jar -Xmx1024M。这提供了一种使用更多堆内存来运行程序的方法,并且因为它允许在给定的prolem中使用它,所以这不是我提交失败的原因。
虽然我不确定,性能可能是机器人失败的原因之一。
关于您的解决方案,
如果我创建一个Map,然后将数字存储在adjacencey列表中,它将为我节省一些空间,但每次我需要在bfs / dfs遍历期间访问节点时,它还会添加额外的查找。这困扰我。你是说我不应该创建邻接列表吗?我明白你要说的正确吗?
感谢。