在Java中,最快速的比较两个字符串的方法是什么?
是否有比equals方法更快的方法?
编辑: 我无法帮助澄清问题。
我有两个按字母顺序排序并且大小完全相同的字符串
例如:abbcee和abcdee
字符串可以长达30个字符。
我并不认为Sun Oracle没有将标准的String#equals()
优化到极致。因此,我希望它已经是最快的方法。如果您想了解它们如何实现,请查看其源代码。以下是一个摘录:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
hashCode()
循环遍历字符串的所有字符来执行计算。如果 hashCode()
最终不相同,那么 equals()
基本上需要再次循环遍历所有字符。 - BalusChashCode()
方法将哈希码存储为int类型,所以下次比较会非常快。 - Stephan使用哈希码快速比较相同长度的字符串:
public static boolean equals(final String s1, final String s2) {
return s1 != null && s2 != null && s1.hashCode() == s2.hashCode()
&& s1.equals(s2);
}
您可以进行测试,我的结果包括4000000个比较操作,其中包括相同的、相等的和不同的字符串:
String.equals(String): 177081939
equals(String, String): 44153608
注意: 计算新字符串对象的hashCode需要一些计算时间,然后将hashCode存储在对象中。因此,我的建议只有在重用字符串对象时才比默认的比较方法更快。在我的应用程序中,我使用String常量并将字符串存储在集合中。使用我的方法进行多次字符串比较实际上对我来说更快,但这可能不是普遍情况。
如果该方法一直用于新字符串,例如compare("a", "b")
,那么它不会有所改善。
因此,比较字符串的最快方式取决于以下因素:
忽略这些事实,大多数程序都可以使用String.equals()方法。
s1.equals(s2)
。 - vedi0boy我曾尝试过不同的字符串比较组合(代码在这里):
1. s1.equals(s2)
2. s1.length() == s2.length() && s1.hashCode() == s2.hashCode() && s1.equals(s2)
3. s1.hashCode() == s2.hashCode() && s1.equals(s2);
4. s1.length() == s2.length() && s1.equals(s2);
我使用了长度为40的字符串,在进行10000000000次迭代之前,我重新初始化了这些字符串。
对于相等的字符串,我的结果是:
equal: 2873 milis ???
equal: 21386 milis
equal: 7181 milis
equal: 2710 milis ???
对于长度相同但最后一个字符不同的字符串:
different: 3011 milis
different: 23415 milis
different: 6924 milis
different: 2791 milis
对于不同的大小,s2中几乎相同的字符串末尾添加了一个字符:
different size: 3167 milis
different size: 5188 milis
different size: 6902 milis
different size: 2951 milis
在使用equals()方法之前,最好先使用string.length()进行比较。
但是,这几乎没有影响,因为我需要进行10^10次字符串比较,每个字符串有40个字符长度,对我来说奇怪的是,对于相等的字符串,当我先比较字符串长度时,速度更快。
如果你能证明它是一个重要的瓶颈,这会让我感到惊讶,但你可以尝试
s1.hashCode() == s2.hashCode() && s1.equals(s2)
它可能会更快。也可能不会。
String
的哈希码并不是在每次调用时计算的。由于String
是不变的,它们可以在内部预先计算或缓存,并且实际上也是这样做的。 - user207421我非常确定(这个答案有一些参考),很可能JIT会对String#equals
进行内置处理,这意味着它能够替换调用,使用特别定制的机器代码来适配当前运行在你的JVM体系结构上。
一如既往,您需要为您的应用程序/环境进行基准测试。除非您已经对其进行了分析并确定其为性能瓶颈,否则这可能并不重要(“过早优化是万恶之源”)。
话虽如此:
a.equals(b) 对于字符串来说是非常快速的。这可能是Java平台中最紧密优化的代码之一。如果您能找到任何更快的比较两个任意字符串的方法,我会非常惊讶。
有特殊情况可以安全地使用(a==b)进行欺骗,例如,如果您知道{{link1:两个字符串都被interned}}(因此值标识意味着对象标识)。在这种情况下,它可能比a.equals(b)稍微快一些-但这又取决于编译器/JVM实现。如果您不知道自己在做什么,很容易自食其果.....
equals()
和 intern 字符串。equals()
方法确实会检查身份。 - Stephan
equals()
方法对你来说会很慢? - BoltClockString.equals(...)
引起的?如果你还没有对你的应用程序进行性能分析,那么为什么认为String.equals(...)
可能会是一个问题? - Bart Kiersequals()
更快的东西,那么要么你有一些非常具体的性能要求,并且有相应的测量数据(在这种情况下,在提供任何适当的答案之前必须发布这些数据),要么你实际上并没有(不寻常的性能要求),在这种情况下,你应该只使用equals()。暗示“equals不够快”而没有任何理由,让人们无从下手。 - Andrzej Doyle