【问题标题】:Way to save memory on adjacencylist在邻接列表上节省内存的方法
【发布时间】:2019-03-30 14:34:02
【问题描述】:

我正在尝试创建邻接列表。问题是我的实现在内存中花费了很多......

我读了一个单词文件,将它们添加到我的图表中并添加图表的邻居

static public void createEdges(){
    for(String string : words){  //words is the list of all the ~4 000 words that have been read
        ArrayList<String> wordlist = new ArrayList<String>();
       // ........................................................
       //(irrelevant part where I create a new String "word" from "string")
       // .........................................................
                    if (Contains(word) != null){  //Contains checks if the new String "word" is a part of the file I read. 
                        wordlist.add(word);
                    }
        list.put(string, wordlist); //list is of type: Hashtable<String, ArrayList<String>>; and represents the wordgraph where "string" is the node and "wordlist" is the neighbors of the node
    }}

我认为节省内存的一种方法是不创建一个新的 ArrayList evere 循环,因为它会循环约 4 000 次......但是我想不出任何好的方法来存储我的相邻节点。使用这种数据结构是否注定要达到我的目的,还是有更聪明的方法来实现它?

【问题讨论】:

  • 这段代码有点混乱。变量“list”、对象“Contains”和变量“word”没有上下文。没有更多的上下文,将很难提供帮助。另外,你怎么知道这会消耗太多的内存?你想达到什么目的?
  • @aglassman 是的,我现在明白了,谢谢。 Contains 是一种简单检查我读取的文件是否包含新字符串“单词”的方法。列出邻接列表,因此列表中的变量“string”是节点,变量“wordlist”是邻居的 ArrayList。我正在制作一个 BFS,以找到从一个词到另一个词的方式。我想实现一个尽可能快地支持这种搜索但又不存储太多数据的数据结构,我觉得这样做是因为它创建了大量的 ArrayLists...
  • 有趣的问题,但我不明白你将列表放入地图的部分。由于您正在为每个 for 循环迭代创建一个新的 ArrayList,所以 Hashtable 中的每个条目不会是一个条目吗?

标签: java arraylist graph-theory adjacency-list


【解决方案1】:

我认为如果编码正确,您的方法不应该占用太多额外的内存。您可以通过确保使用要添加的元素数量来初始化 ArrayList 来节省内存。这可能适用于您的算法,也可能不适用于您的算法。

您可能必须在确定所有值后创建一个新的 ArrayList,然后将结果复制到其中。这将减少列表将分配的多余容量。当数组列表达到其内部容量时,它必须分配更多内存。

这只会为每个 ArrayList 节省几个字节,因此只有在映射中有大量条目时才值得。

ArrayList vs LinkedList from memory allocation perspective

另一个需要考虑的方面是 String 对象占用了多少空间。看来您正在引用一个文件和一个单词列表。如果文件可以作为大字符串(最大大小约为 2GB)保留在内存中,那么所有 .substring 调用都将只是“windows”进入该文件。如果您正在创建新的 String 对象,则会占用更多内存。

Why does appending "" to a String save memory?

【讨论】:

  • 你的意思是像:ArrayList&lt;String&gt; wordlist2 = new ArrayList&lt;String&gt;(wordlist.size()); for(String tmp: wordlist){ wordlist2.add(tmp); }
  • 是的,这可能会为您节省几个字节。
  • 我找到了一个代码,它将每个读取的单词添加到 Hashtable wordlist2; 中。添加邻居时,不是像这样添加它:list.put(string, wordlist);,而是像这样添加:list.get(string).add(wordlist2.get(word));。这运行速度较慢,但​​可以节省更多内存。知道为什么吗?
  • 这更有意义。您首先从地图中获取列表,然后从第二个列表中添加字符串。这样您就不会每次都创建一个新列表,并且您还在两个列表中引用相同的字符串对象。
猜你喜欢
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 2014-01-07
相关资源
最近更新 更多