散列长字符串进行比较或比较两个字符串是否更快?

时间:2015-03-24 16:34:48

标签: java string performance hash

假设我有一个非常长的字符串列表(40-1000个字符)。用户需要能够在列表中输入术语,列表将报告术语是否存在。

禁止存储,在长字符串旁边存储哈希是否更有效,然后当用户尝试查找时,它会哈希输入并将其与哈希列表进行比较?

There are similar answers here, but they aren't quite generalized enough.

2 个答案:

答案 0 :(得分:3)

假设数据适合堆(即在内存中),最好的办法是使用Set(如果有与每个字符串相关的数据,则使用Map)。如果您确实需要List,则可以将存储从List更改为Set(使用HashSet)或维护单独的Set。

计算字符串hashcode()的时间与字符串的长度成正比。假设正确实现的hashcode()和适当大小的Set,查找字符串的时间相对于集合中的字符串数量(一旦计算出哈希码)是恒定的。

如果您在未排序的列表中使用equals(),则查找时间可能与列表中的项目数成比例。如果您对列表进行排序,则可以使用比较次数进行二进制搜索,以查找与列表中项目数的对数成比例的一个字符串(并且每次比较都必须比较字符,直到找到差异为止)。 / p>

本质上,Set有点像保持字符串的哈希码一样方便,但它更进一步,并以这样的方式存储数据,以便快速直接跳转到集合的元素哈希码值。

请注意,只要找到差异,两个字符串的等于比较可以挽救,但可能必须比较两个字符串中的每个字符(当它们相等时)。如果您的字符串具有类似的长前缀,则会影响性能。有时,您可以从对数据类型内容的了解中获益(性能方面)。例如,如果所有字符串都以相同的1K前缀开头并且最后只有不同,那么您可以从覆盖equals()实现以从结束到开始进行比较中受益,因此您可以更早地发现差异。

答案 1 :(得分:0)

你的问题不够具体。

首先,我假设你的意思是"我有 set 非常长的字符串",因为 list 是非常低效的状态查找结构

一些想法:

  • 取决于字符串的属性'设置(即域),前缀树在内存和速度方面可能比任何类型的哈希表都显着提高效率。前缀树意味着比较,而不是哈希计算。
  • 否则,您最终应该使用某种哈希表,这意味着您应该至少计算一次哈希码,每个字符串至少一次。在这种情况下,将哈希码与字符串一起存储似乎是合理的。但是为了严格正确,最后你应该按内容比较字符串,因为哈希冲突是可能的。
  • 理论上,分布均匀的散列函数的最大速度是3-4字节/时钟周期(即散列函数每CPU周期消耗3-4个字节)。
  • 流比较的速度 - 取决于某些条件以及代码的编译方式,现代CPU上有一些指令允许每个周期最多比较16个字节。有趣的是,Arrays.equals方法是内在的,但没有" raw" sun.misc.Unsafe类中的内存比较方法。