标题说明了一切。我的问题是关于不同String
等效方法的效率。我经常使用.equalsIgnoreCase(String str)
,因为我只是有一件事。但我开始怀疑它是不是找到Strings
之间等效性的最有效方法。在我看来,.equalsIgnoreCase(String str)
正在调用一种案例转换方法toUpperCase
或toLowerCase
,然后在其定义中调用equals
,但我可能错了。那么,在下列情况下,哪种方法更有效,或者在任何情况下更有效?
int count = 0;//checks for face cards at indexes listed in selectedCards
// Selected cards is Integer ArrayList
for(; (count < selectedCards.size() && count < 3); count++)
{
if(cardAt(selectedCards.get(count)).rank().equalsIgnoreCase("Queen"))
count++;
else if(cardAt(selectedCards.get(count)).rank().equalsIgnoreCase("King"))
count++;
if(cardAt(selectedCards.get(count)).rank().equalsIgnoreCase("Jack"))
count++;
}
if(count == 3)
return true;
return false;
答案 0 :(得分:13)
令人惊讶的是,由于某些奇怪的Unicode原因,这些方法并不相同:
toUpperCase("ß")
返回"SS"
,即两个字母,而equalsIgnoreCase
返回字符toUpperCase
和toLowerCase
都不充分的字符,您必须同时执行这两项操作关于效率,我敢打赌equalsIgnoreCase
速度更快,因为它不会复制任何数据。它也从长度比较开始。
另请注意,toUpperCase
和toLowerCase
是Locale
- 敏感,而equalsIgnoreCase
则不是。enum
。如果使用异域现场,IIRC的性能会下降。
最好和最简单的优化是预先对套管进行标准化。没有理由拥有&#34; Queen&#34;,&#34; queen&#34;和&#34; Queen&#34;在您的数据中 - 尽快清理输入。
您还可以使用if (x) return true; else return false;
来表示排名。
我害怕,你的循环被打破了。在任何一个JQK之后你跳过一张卡,那就是那个???
执行以下操作
return x;
替换为enum
不使用int count = 0;
// Whatever Position is
for (Position p : selectedCards) {
String rank = cardAt(p).rank();
if (rank.equalsIgnoreCase("Jack")
|| rank.equalsIgnoreCase("Queen")
|| rank.equalsIgnoreCase("King")) {
++count;
if (count > 3) { // Tiny and probably useless optimization.
return false;
}
}
return count == 3;
和早期标准化的代码如下所示:
{{1}}
答案 1 :(得分:12)
JMH使微基准测试更容易:
更新:将输入字符串设置为参数,以解决JMH God Alexey Shipilev的评论。我将目标字符串保持不变,因为OP的用例是将输入字符串与常量进行比较。
@State(Benchmark)
public class StrComp {
@Param({"Queen", "queen", "King"})
public String input;
@Benchmark
public boolean eqIgnoreCase() {
return input.equalsIgnoreCase("queen");
}
@Benchmark
public boolean eqToLower() {
return input.toLowerCase().equals("queen");
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(".*StrComp.*")
.mode(Mode.AverageTime)
.timeUnit(TimeUnit.NANOSECONDS)
.forks(5)
.warmupIterations(10)
.measurementIterations(10)
.build();
new Runner(opt).run();
}
}
输出:
Benchmark Mode Cnt Score Error Units
StrComp.eqIgnoreCase avgt 50 18.581 ± 0.051 ns/op
StrComp.eqToLower avgt 50 54.796 ± 0.173 ns/op
使用参数
更新输出Benchmark (input) Mode Cnt Score Error Units
StrComp.eqIgnoreCase Queen avgt 50 17.947 ± 0.205 ns/op
StrComp.eqIgnoreCase queen avgt 50 15.553 ± 0.159 ns/op
StrComp.eqIgnoreCase King avgt 50 2.968 ± 0.037 ns/op
StrComp.eqToLower Queen avgt 50 56.499 ± 0.180 ns/op
StrComp.eqToLower queen avgt 50 22.023 ± 0.040 ns/op
StrComp.eqToLower King avgt 50 49.174 ± 0.145 ns/op
所以,eqIgnoreCase更快,但除非你每秒进行一百万次比较,否则你不会发现任何差异。
如果第一个字符串已经是小写字母或者字符串的长度不同等,您可以四处玩,看看差异会受到什么影响。
无论如何,如果你想让你的代码更有效率,那么#34;而且更清晰,类型安全且不易出错,不要使用字符串来做这样的事情。使用枚举。
卡片非常适合通过枚举实现,它常用于说明enum
概念:http://docs.oracle.com/javase/8/docs/technotes/guides/language/enums.html#Card
答案 2 :(得分:6)
您可以自己检查代码(它包含在SDK中)。
.equalsIgnoreCase比toUperCase()更快.qualals() 在java 8中,代码是:
while (len-- > 0) {
char c1 = ta[to++];
char c2 = pa[po++];
if (c1 == c2) {
continue;
}
if (ignoreCase) {
// If characters don't match but case may be ignored,
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
}
return false;
}
return true;
因此,如果比较的字符串实际上是不同的,那么它将比首次调用toUpderCase更快,然后等于toUperCase将修改所有字符。此外,toUperCase中涉及的逻辑似乎比比较循环更复杂,它最后会创建一个新的String对象。
但是您需要进行大量的比较操作才能真正看到任何差异。