好的,这是我的情况:
我有一个状态数组,可能包含重复项。为了摆脱重复,我可以将它们全部添加到Set。
但是,当我创建Set时,它需要定义初始容量和负载因子,但它们应该设置为什么?
从谷歌搜索,我想出了:
String[] allStates = getAllStates();
Set<String> uniqueStates = new HashSet<String>(allStates.length, 0.75);
这个问题是allStates可以包含1到5000个状态。因此,Set的容量将超过5000,但最多只能包含50个。
因此,设置Set的最大大小可以设置为最大状态数,负载因子为1。
我想我的问题确实是:
答案 0 :(得分:12)
假设你知道不会超过50个州(你的意思是美国吗?),
Set<String> uniqueStates = new HashSet<String>(allStates.length, 0.75);
引用绝对是错误的。我建议你的初始容量为50 / 0.75 = 67,或者可能是68以保证安全。
我也觉得有必要指出你可能会过度强调这一点。将arraylist从16提升到64再调整为64,除非在程序中性能最关键的部分正确,否则不会给你带来明显的性能提升。
所以最好的答案可能就是:
new HashSet<String>();
这样,一年之后你就不会回来了,并且为什么选择这样奇怪的构造函数参数而感到困惑。
答案 1 :(得分:7)
使用您不需要指定这些值的constructor,然后选择合理的默认值。
答案 2 :(得分:2)
首先,我要说的是,在你的情况下,你肯定会过度思考它。但是,有可能会有人想要做对。所以这就是我的理解:
1)您可以在HashSet中保存的项目数=初始容量x负载系数。因此,如果您希望能够容纳n个项目,则需要执行Zarkonnen所做的操作,并将n除以加载因子。
2)在封面下,初始容量四舍五入为per Oracle tutorial的幂。
3)负载因子不应超过.80,以防止过度碰撞,如Tom Hawtin - tackline所述。
如果你只接受默认值(初始容量= 16,加载因子= .75),你最终会将你的设置加倍3倍。 (初始最大尺寸= 12,第一次增加使容量32和最大尺寸24(32 * .75),第二次增加使容量64和最大尺寸48(64 * .75),第三次增加使容量128和最大尺寸96(128) * .75)。)
要使最大尺寸接近50,但保持设置尽可能小,请考虑初始容量为64(2的幂)和0.79或更大的负载系数。 64 * .79 = 50.56,所以你可以获得所有50个州。指定32&lt;初始容量&lt; 64将导致初始容量四舍五入到64,这与预先指定64相同。指定初始容量&lt; = 32将导致大小增加。使用负载因子&lt; .79也会导致尺寸增加,除非您的初始容量> 64。
所以我的建议是指定初始容量= 64和加载因子= .79。
答案 3 :(得分:1)
安全赌注的尺寸太小了。
因为调整大小可以通过指数增长算法得到改善(请参阅几周之后的stackoverflow播客),小一点也不会花费你那么多。如果你有很多套装(幸运的话),那么如果它们超大则对性能很重要。
负载系数是一个棘手的问题。我建议保留默认值。据我所知:低于约0.70f,你使阵列太大,因此更慢。高于0.80f,你将开始进行许多关键冲突。推测探测算法需要比桶算法更低的负载因子。
另请注意,“初始容量”意味着与大多数人认为的略有不同。它指的是数组中的条目数。要获得多个元素的精确容量,请除以所需的负载因子(并适当地舍入)。
答案 4 :(得分:0)
做个好猜。没有硬性规定。如果你知道可能会说10-20个州,我会从那个数字开始(20)。
答案 5 :(得分:0)
我是第二个Zarkonnen。你的最后一个问题是最重要的问题。如果这恰好发生在应用程序的热点中,那么查看它并尝试优化可能是值得的,否则CPU周期比烧毁自己的神经元便宜。
答案 6 :(得分:0)
如果您要对此进行优化 - 并且可能适合这样做 - 您的一些决定将取决于您期望阵列具有多少重复项。
如果有很多重复项,您需要一个较小的首字母 容量。迭代时,大的稀疏哈希表很糟糕。
如果预计不会有很多重复项,您需要 一个初始容量,使整个阵列可以适应没有 大小调整。
我的猜测是你想要后者,但如果你追求这个,这是值得考虑的事情。