【发布时间】:2013-01-27 21:04:32
【问题描述】:
我想知道 Java 中 .equals 运算符对于两个字符串的时间复杂度(大 O)是多少。
基本上,如果我执行 stringOne.equals(stringTwo),它的性能如何?
谢谢。
【问题讨论】:
-
你会怎么想?您认为平等检查是如何实施的?
-
如果两个
Strings都被interned,可以在恒定时间内完成。
我想知道 Java 中 .equals 运算符对于两个字符串的时间复杂度(大 O)是多少。
基本上,如果我执行 stringOne.equals(stringTwo),它的性能如何?
谢谢。
【问题讨论】:
Strings都被interned,可以在恒定时间内完成。
这里的其他答案过于简单了。
一般来说,证明两个不同的字符串相等是O(n),因为您可能必须比较每个字符。
但这只是最坏的情况:有许多捷径意味着equals() 方法在平均/典型情况下的表现要好得多:
O(1):它们是同一个对象,因此根据定义相等,因此结果为真O(1) 如果您能够检查预先计算的哈希码,这可以证明两个字符串不相等(显然,它不能帮助证明两个字符串相等,因为很多字符串哈希到相同的哈希码)。O(1)(它们不可能相等,因此结果为假)O(1) 时间。如果您的字符串不是完全随机的,则结果可能介于 O(1) 和 O(n) 之间,具体取决于数据分布。如您所见,确切的性能取决于数据的分布。
除此之外:这是依赖于实现,因此确切的性能特征将取决于所使用的 Java 版本。但是,据我所知,当前所有主要的 Java 实现都进行了上面列出的优化,因此您可以期望 equals() 在字符串上的性能非常快。
最后一个技巧:如果您使用 String interning,那么所有相等的 String 都将映射到同一个对象实例。然后,您可以使用极快的== 检查对象身份来代替equals(),保证为O(1)。这种方法有缺点(您可能需要实习很多字符串,这会导致内存问题,并且您需要严格记住要实习您计划与此方案一起使用的任何字符串),但在某些情况下它非常有用。
【讨论】:
== 比较一个非内部字符串,那么您的代码可能会中断。这会使您的应用程序变得脆弱。
最坏的情况是 O(n),除非两个字符串是同一个对象,在这种情况下是 O(1)。
(虽然这里的n指的是从第一个字符开始的两个字符串中匹配的字符数,而不是字符串的总长度)。
【讨论】:
Strings 的长度是否相同。
为了增加出色的答案,我们可以查看代码:
public boolean equals(Object anObject) {
if (this == anObject) { // O(1)
return true;
}
if (anObject instanceof String) //O(1) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) { // O(1)
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) { // O(n)
if (v1[i] != v2[i]) //O(1)
return false;
i++;
}
return true;
}
}
return false;
}
最佳情况:O(1)
最坏情况:O(n)
【讨论】: