微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java:再次存储字符串集的最佳数据结构

如何解决Java:再次存储字符串集的最佳数据结构

鉴于我们有一个字符串列表,我想知道最有效的数据结构是什么,它可以验证给定的字符串是否已经存在,如果不存在,则添加它。

我的第一个选择是HashSet<String>,它在检查字符串是否存在时具有O(n)(最理想的情况)的复杂性。但是,当将被重载时,将基于hashCode算法逐个字符地对每个字符串进行重新哈希处理: s[0]*31^(n - 1) + s[1]*31^(n - 2) + ... + s[n - 1] 会导致O(n^2)的原因。

编辑: 我要强调的是,我这里最大的担忧是,由于有很多相当长的唯一条目,因此在重新哈希HashSet时重新哈希每个字符串的时间复杂度。

是否有更好的方法在HashSet中存储许多字符串,或者有更好的数据结构?

解决方法

您的第一个想法是错误的。答案是HashSet。期间。

您对碰撞的关注与您无关。尝试将现有字符串添加到集合中不会执行任何操作。发生冲突的唯一方法是添加很多完全出于巧合而具有相同哈希码的字符串,这不会发生... 除非,某人有意试图与您打乱,以便为合法用户运行服务器账单或拒绝服务。

如果是这种情况,则需要付出可观的费用:您需要一种密码安全的哈希算法。您当然可以这样做,但这会使事情变得更加复杂。该模型将是相同的(具有一个哈希表,其键基于custom_hash_algo("input")的结果,并且其值为List<V>:使用custom_hash_algo哈希到同一键的每个值。然后,您可以使用此方法重新实现Set的所有方法(字面意思是:创建一个extends AbstractSet<V>类,其中大多数方法都是在该内部映射上调用方法的单行代码。

custom_hash_algo将成为您所需要的。如果要防止有人故意向您喂散列冲突的字符串,则可以使用一种简单的阻止机制(如果给定自定义散列值的列表中的条目过多,则仅当机并拒绝服务,这很可能会导致这种情况)字面上的99.9999%表示客户正与您打扰或反过来被打扰)或加密安全的哈希值。

如果您有其他理由相信哈希冲突会比预期的“对于任意两个给定的字符串,它们碰撞的几率是40亿中的1”更频繁,则可以使用完全相同的原理其他非加密算法(因此对于有意创建碰撞字符串的鲁棒性也不强)。


注意:如果我误解了您的问题,而您唯一担心的是,字符串的hashCode()含义将着眼于每个字符:不,您不能对此进行改进;不可能对字符串进行散列以免避免冲突,除非您不这样做,除非您知道特定字符串的某些特定知识不适用于任意字符串(“它们始终以唯一的8字符ID开头!”-好的,那么也许您可以将其用于哈希)。

这也不等于O(n^2)。在讨论算法复杂性时,如果没有定义n的实际含义,则无法做到这一点。从上下文通常很明显,这就是为什么通常不说的原因,但是即使没有说,它仍然是声明的关键部分。在您的情况下,“设置的字符串数”是一个变量,而“字符串的平均长度”是另一个变量。充其量您可以说是O(n*m)(其中n和m定义为“ n =集合的大小,m =其中字符串的平均长度”)。是的。显然,这是最有效的方法。

NB2:编​​写Map<Integer,List<V>>支持的set impl时,一个重要的优化机会是使值不是List<V>而是Object,这样您就可以制定规则是一个非列表对象,那么在您的集合中只有一个散列为此值的对象,并且只有在发生冲突时,您才能创建一种特殊的内部列表类型(这就是您的区分方式:没人,但您可以做到这一点内部列表类型,因此,如果是该类型,则说明是冲突情况。这样可以节省很多的开销。

,

该构造函数不是一个选择吗?

public HashSet(int initialCapacity,float loadFactor)

,

这里更一般的情况是:如何实现数组映射

如果数组(或字符串)经常很大,则哈希码计算将成为负速度因子。因此,HashMap可能不是一个好主意。

然后TreeMap会更好,因为通常会进行比较:

  1. 相同长度;
  2. 只要元素相等,就比较数组元素。

换句话说:

  • 给出 N 个数组的数量
  • 给出 L 数组的平均长度

然后是一般情况:

  • HashMap:O(N * L)
  • TreeMap:大约。 O(N * log(N)* log(M))

这意味着您必须进行基准测试。

当字符串很大(例如包含文件)时,所有这些都变得有意义。您还可以通过压缩并使用哈希码(CRC?)存储字节来“优化”这些东西。

作为针对接口(Set<String> set)的一个程序,可以推迟实现的选择。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。