内存效率:HashMap与Array

时间:2014-01-28 23:27:18

标签: java arrays hashtable

我正在考虑以下情况:我想计算字符串中字符的出现次数(例如,用于排列检查)。

一种方法是分配一个256个整数的数组(我假设字符是UTF-8),用零填充它然后通过字符串并增加数组位置对应的整数到字符的int值。

但是,对于这种方法,每次都必须分配256个数组,即使分析的字符串非常短(因此只使用数组的一小部分)。

另一种方法是使用Character to Integer HashTable并为每个遇到的char存储一个数字。这样,你只能拥有实际存在于字符串中的字符键。

由于我对HashTable的理解是相当理论的,我真的不知道它是如何用Java实现的,我的问题是:这两种方法中哪一种更有效?

编辑:

在讨论这个问题时(谢谢大家的答案)我意识到我对UTF-8的本质有一个非常模糊的理解。经过一番搜索后,我发现了我想要分享的this great video,以防有人遇到同样的问题。

5 个答案:

答案 0 :(得分:6)

我想知道为什么当你假设你的String是UTF-8时你选择256作为数组的长度。在UTF-8中,一个字符最多可以由4个字节组成,这意味着比256个字符多得多。

无论如何:使用HashTable / HashMap需要巨大的内存开销。首先,所有字符和整数都需要包装在一个对象中(整数/字符)。整数占用的内存大约是int的3倍。对于数组,由于java对数组执行的优化(例如,java堆栈仅在4字节的倍数下工作,而在数组java中允许较小的类型,如char只消耗2个字节),因此差异可能更大。

然后HashTable本身会产生内存开销,因为它需要维护一个数组(通常没有完全使用)和链接列表来维护生成相同哈希的所有对象。

此外,阵列的访问时间将大大加快。您可以保存多个方法调用(add,hashCode,iterator,...),并且在java字节代码中存在许多操作码,以便更有效地处理数组。

反正。你的问题是:

  

这两种方法中的哪一种会更节省内存?

可以肯定地说,数组的内存效率更高。

但是你应该绝对确定你的要求是什么。你需要更高的内存效率吗? (如果您处理大量数据或者您使用的是慢速设备(移动设备?),可能会出现这种情况吗?)代码的可读性有多重要?代码大小怎么样?可重用?

ist 256真的是正确的尺寸吗?

答案 1 :(得分:3)

在不查看代码的情况下,我知道HashMap至少需要一个基础对象,一个哈希表数组和每个哈希项的单个对象。通常,int值必须存储为Integer对象,以便更多对象。假设你有30个独特的字符:

  • 基础对象的32个字节
  • 最小大小哈希表数组的256字节
  • 30个表条目中的每一个的32个字节
  • 30个整数
  • 中的每个字节(如果高度优化)

32 + 256 + 960 + 480 = 1728字节。这是一个最小的,非花哨的实现。

256个int的数组大约是1056个字节。

答案 2 :(得分:1)

我会使用数组。从性能方面来说,您可以保证持续访问。比散列表可以获得的更好。

因为它也只使用恒定的内存量,所以我没有看到任何缺点。 HashMap很可能需要更多内存,即使您只存储了一些元素。

顺便说一下,内存占用不应该是一个问题,因为只要你需要数据结构,你就只需要数据结构。无论如何,它将被垃圾收集。

答案 3 :(得分:1)

这是事实。

  • HashMap在幕后为其表使用数组。

因此,如果你实际上受限于在内存中找到一个连续的空间,那么HashMap的好处只在于数组可能更小。

  • HashMap是通用的,因此使用对象。

对象占用额外的空间。我记得,它通常最小为8或16个字节,具体取决于它是32位还是64位系统。这意味着即使String中的字符数很小,HashMap也可能不会更小。 HashMap每个条目需要3个额外的对象:EntryCharacterInteger。 HashMap还需要在本地存储索引的int,而数组则不需要。

除此之外,使用HashMap还会有一些额外的计算。

我还想说空间优化不是你应该担心的。无论哪种方式,内存占用量实际上非常小。

答案 4 :(得分:0)

初始化一个表示char的int值的整数数组,例如f的int值为102,即ascii值

http://www.asciitable.com/

char c = 'f';
int x = (int)c;

如果你知道你正在处理的char的范围,那就更容易了。

对于每个char的出现,将数组中该char的索引加1。如果你要进行迭代和复杂,如果要进行排序但不会占用大量内存,这种方法会很慢。

请注意,在排序时会丢失索引