虽然我非常了解HashCode是什么以及哈希表的作用,但我不得不承认我不知道如何使用它(超越常用词典)。我想实现自己的Hash Table,所以首先我想知道关于Hash的基本知识:
getHashCode()
/ hashCode()
获取哈希码。这个数字是如何确定的。 (只是出于好奇)HashCode
,我该如何访问它?也就是说,我该如何调用该内存桶?HashCode
吗?现在,我有一个非常大的(约10 ^ 9)Int列表。我将访问其中一些(从无到有),我需要尽可能以最快的方式完成。哈希表是最好的方法吗?
PS:我不想讨论它,我只是想知道HashTable是否知道是最有效的。如果还有其他好的方法,你可以指点我。
谢谢,
答案 0 :(得分:6)
哈希码只是一个数字,保证与原始对象“相同”的每种类型的对象相同。
这意味着为每个哈希代码调用返回“0”将是有效的,但是会弄巧成拙。关键是可以(并且在大多数情况下)会重复。
如果您知道对象的哈希码,则无法访问它。根据上面的例子,如果所有对象都返回“0”,你仍然无法询问哪个对象有哈希码0.但是,你可以要求哈希码为0的所有对象并查看它们(这是哈希表的作用,它通过只获取具有相同哈希码的那些来减少迭代量,然后查看那些)。
如果您要设置(更改)HashCode,它将不是哈希码,因为给定“State”的对象的值不能更改。
对于执行此操作的“最佳方式”,返回相同哈希码的唯一对象越少,哈希表的执行效果就越好。如果你有一个很长的“int”列表,你可以使用那个int值作为你的哈希码,你就会得到那个罕见的完美哈希 - 每个对象只映射一个哈希码。
请注意,哈希表并不适合这种存储int的情况。对于您尝试存储不易于使用其他机制进行唯一标识或比较的复杂对象的情况,这种情况会更好。
你的“Int of List”的问题在于,如果你有5号并且你想在你的表中查找它,你就会在那里找到5号。
现在,如果您想查看表中是否存在数字5,那就是另一回事了。
对于一组有少数孔的数字,你可以制作一个简单的布尔数组。如果[5]存在(是真),则列表中有a。如果你的数字组很稀疏(1,5,10002930304),那么这不是一个很好的解决方案,因为你在第2,3,4点存储“False”,然后在最后一个存储它们之前的一大堆数字,但它是一个直接查找,无论你添加多少个数字,都不会再花费一步 - O(1)。
你可以通过对字节数组进行二进制查找来使这种类型的存储更加密集,但除非你对位操作非常好,否则跳过它。它会涉及看起来像这样的东西:
public boolean doesNumberExist(int number) {
return bytes[number / 8] & ( 1 << number % 8);
}
如果您的最高人数真的很大,这仍然会耗尽内存。
因此,对于大型稀疏列表,我将使用排序整数数组而不是轻微填充的布尔数组。一旦它被排序为数组,你只需进行二分查找;从排序数组的中间开始,如果您想要的数字更高,则将中间列表的上半部分划分并检查该数字,重复。
已排序的int数组需要更多步骤但不会太多,并且不会为不存在的数字浪费任何内存。
答案 1 :(得分:0)
散列函数返回一个整数。您使用该整数(键)作为索引来存储您的信息。在java中,您可以使用java.util.Hashtable。您可以随时滚动自己,它可以像使用键作为索引的数组一样简单。
对于您的程序,您确实需要弄清楚如何访问元素。哈希表提供对特定项的超快速访问,但不(不应)提供顺序访问
如果你正在使用java,请查看哈希表,看看这些方法是否适合你的应用程序:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.html
答案 2 :(得分:0)
Int的大列表作为我通过索引访问的查找表。然后我猜索引将是关键,列表元素是值。希望澄清它
在这种情况下,java.util.HashTable
并不比java.util.ArrayList
好。 HashTable
将消耗至少两倍的内存,同时提供稍慢的访问。
甚至比ArrayList更好的是普通int[]
,因为不需要创建和存储整数实例。我估计这会将内存消耗减少3倍。
然而,将10 ^ 9 int
保留在内存中仍然是一个令人生畏的命题,因为每个int
消耗4个字节的内存。那是4 GB。您可能希望将至少部分列表保存在磁盘而不是内存中,并使用例如RandomAccessFile来查找正在查找的索引。