我知道我们总是谈论自动装箱时的性能损失,但我想知道这是否会影响算法的Big O复杂性。
Character类的构造函数的Java实现是:
public Character(char value) {
this.value = value;
}
构造函数是常量时间,因此它实际上归结为对象创建。对象创建会影响Big O时间吗?例如,如果你将String
的字符放入HashSet<Character>
仍然是O(n),其中n是字符串中的字符数?
答案 0 :(得分:2)
简短的回答是否定的。它不会改变复杂性。
在所有情况下,自动装箱单个值的复杂性为O(1)
。平均而言,将单个元素添加到HashSet的成本是O(1)
摊销的。一次完成这两件事的成本仍然是平均O(1)
。
将元素添加到HashSet
的实际成本变化很大。可变性归因于两件事:
由于哈希函数选择不当或“运气不好”导致的哈希冲突,可能导致HashSet
搜索长哈希链。在最坏的情况下,可以是O(N)
。举个例子,这些东西不适用 1 。
如果HashSet
中的元素数量不断增加,它将定期重新分配其哈希数组并重新创建哈希链。但是,由于HashSet
算法每次都会使数组大小加倍,因此摊销的开销不会改变每次插入的O(1)
平均成本。
自动装箱的实际成本也是可变的。对于某些原语,相应的Wrapper类型为原始值范围的子集维护先前实例化的自动装箱值的高速缓存。如果valueOf(prim)
给出缓存命中,则不会分配新对象。
对于您的示例,Character
缓存U0000到U007F的盒装值。
有人提到内存分配的成本不一定是O(1)
。这在技术上是正确的。但是,为了达到比O(1)
更糟糕的行为,你需要做一些不好的事情; e.g。
解决这些问题的方法往往是增加堆大小,购买更多内存,获得更强大的机器......或重新设计算法。
1 - 最差情况行为O(N)
仅在散列函数不良和/或不幸的元素模式时发生。对于原始包装器,前者不可能发生:例如,查看Character::hashCode()
的实现。后者不可能发生,因为Character
实现Comparable
。