Java 哈希表非恒定时间操作
Java Hashtable Non-Constant Time Operations
我目前正在研究 Java 中的散列 tables,我对散列 tables 的操作及其执行速度有疑问。
我读到哈希 table 可以在常数时间内实现插入、查找和删除等操作,O(1)。我想弄清楚是什么使散列 table 的操作成为非恒定时间的,其中一些操作是什么?
我认为像 size()
这样的操作会在线性时间内进行,因为速度取决于散列的大小 table 但我不确定。
如有任何想法,我们将不胜感激!
在天真的实现中,计算大小是线性的,是的。但将大小缓存在变量中是一种简单的优化,非常值得额外的几个字节和在添加和删除元素时必须更新该变量的轻微性能损失。
请记住,插入是 O(1) 摊销。它并不总是一个恒定的时间操作。如果散列 table 变得过满,插入将导致其大小调整,即 O(n) 操作。幸运的是,这些调整大小很少见,它们的成本可以在其他 O(n) 插入中平均,平均只增加一个常数因子。
另外,插入、查找、删除平均都是O(1),但也可以是O(n) 在最坏的情况下。使用病态糟糕的哈希函数,它们的性能将严重下降。在最坏的情况下,所有元素都将添加到散列 table 中的一个桶中,有效地将散列 table 变成一个链表。
实际上,in Java 8 they added an optimization to HashMap
。如果桶足够大并且键是 Comparable
它将使用二叉树而不是链表,将最坏情况下的性能从 O(n) 提高到 O(log n).
我目前正在研究 Java 中的散列 tables,我对散列 tables 的操作及其执行速度有疑问。
我读到哈希 table 可以在常数时间内实现插入、查找和删除等操作,O(1)。我想弄清楚是什么使散列 table 的操作成为非恒定时间的,其中一些操作是什么?
我认为像 size()
这样的操作会在线性时间内进行,因为速度取决于散列的大小 table 但我不确定。
如有任何想法,我们将不胜感激!
在天真的实现中,计算大小是线性的,是的。但将大小缓存在变量中是一种简单的优化,非常值得额外的几个字节和在添加和删除元素时必须更新该变量的轻微性能损失。
请记住,插入是 O(1) 摊销。它并不总是一个恒定的时间操作。如果散列 table 变得过满,插入将导致其大小调整,即 O(n) 操作。幸运的是,这些调整大小很少见,它们的成本可以在其他 O(n) 插入中平均,平均只增加一个常数因子。
另外,插入、查找、删除平均都是O(1),但也可以是O(n) 在最坏的情况下。使用病态糟糕的哈希函数,它们的性能将严重下降。在最坏的情况下,所有元素都将添加到散列 table 中的一个桶中,有效地将散列 table 变成一个链表。
实际上,in Java 8 they added an optimization to HashMap
。如果桶足够大并且键是 Comparable
它将使用二叉树而不是链表,将最坏情况下的性能从 O(n) 提高到 O(log n).