提问人:Mediator 提问时间:9/28/2010 最后编辑:Mediator 更新时间:8/28/2016 访问量:45382
在 Java 中比较字符串的最快方法是什么?
What's the quickest way to compare strings in Java?
问:
在 Java 中比较两个字符串最快的方法是什么?
有没有比等于更快的东西?
编辑: 我无法帮助澄清这个问题。
我有两个字符串,它们按字母顺序排序,大小完全相同
示例: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()
hashCode()
这取决于你需要什么。我认为equals()确实经过优化,但也许您需要比equals()更快的东西。看看这篇文章。
与往常一样,您需要针对您的应用程序/环境进行基准测试。除非你已经分析并认为这是一个性能瓶颈,否则它可能无关紧要(“过早的优化是万恶之源”)。
话虽如此:
a.equals(b) 对于字符串来说非常快。它可能是 Java 平台中优化最紧密的代码片段之一。如果你能找到任何更快的方法来比较两个任意字符串,我会感到非常惊讶。
在一些特殊情况下,你可以作弊并安全地使用 (a==b),例如,如果你知道两个字符串都被隔离了(因此值标识意味着对象标识)。在这种情况下,它可能比 a.equals(b) 略快 - 但这同样取决于编译器/JVM 实现。如果你不知道自己在做什么,很容易搬起石头砸自己的脚......
评论
equals()
equals()
如果你能证明这是一个重大的瓶颈,这会让我感到惊讶,你可以尝试
s1.hashCode() == s2.hashCode() && s1.equals(s2)
它可能会更快一些。它可能不是。
评论
null
String
String
使用哈希码更快地比较相同长度的字符串:
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.intern() 的使用
忽略这些事实,大多数程序都可以使用 String.equals()。
评论
s1.equals(s2)
我尝试了不同的组合进行字符串比较(代码在这里):
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 个字符的字符串,在 10000000000L 迭代中,在任何迭代之前,我都重新初始化了字符串。
对于我得到的同等蜇伤:
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
在我看来,最好先使用 string.length() 比较,然后再使用 equals()。
但这几乎根本不重要,因为在这种情况下,我有 10^10 个字符串与 40 个字符长度进行比较,对我来说奇怪的是,当我首先比较字符串长度时,对于相等的字符串,我有更好的速度。
评论
简单的答案
我很确定(这个答案有一些参考),并且 JIT 很可能具有 的内在 for,这意味着它将能够用 JVM 当前运行的架构的特制机器代码替换调用。String#equals
评论
equals()
String.equals(...)
String.equals(...)
equals()