equalsIgnoreCase()与toUpperCase()的效率.equals和toLowerCase().equals

Ung*_*uer 10 java string performance

标题说明了一切.我的问题是关于不同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;
Run Code Online (Sandbox Code Playgroud)

maa*_*nus 14

令人惊讶的是,由于某些奇怪的Unicode原因,这些方法并不相同:

  • toUpperCase("ß")返回"SS",即两个字母,同时以equalsIgnoreCase字符方式工作
  • 有些字符既不充分toUpperCase也不toLowerCase充分,你必须同时做到这两点

关于效率,我敢打赌这equalsIgnoreCase会更快,因为它不会复制任何数据.它也从长度比较开始.

还要注意toUpperCasetoLowerCaseLocale敏感的,而equalsIgnoreCase不是.如果使用异国情调的地区,IIRC的性能会下降.

你的用例

最好和最简单的优化是预先对套管进行标准化.没有理由在数据中加入"Queen","queen"和"Queen" - 尽快清理输入.

您还可以使用a enum来表示排名.

我害怕,你的循环被打破了.在任何一个JQK之后你跳过一张卡,那是打算???

简化代码

请执行下列操作

  • 使用foreach循环来保持清洁
  • 使用局部变量来避免重复复杂的表达式
  • 替换if (x) return true; else return false;return x;

不使用enums和早期规范化的代码如下所示:

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;
Run Code Online (Sandbox Code Playgroud)

  • "......预先将套管标准化." - 这,IMO,是正确的答案. (3认同)

Mis*_*sha 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并输出:

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
Run Code Online (Sandbox Code Playgroud)

使用参数更新输出:

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
Run Code Online (Sandbox Code Playgroud)

因此,eqIgnoreCase更快,但除非你每秒进行一百万次比较,否则你不会注意到任何差异.

如果第一个字符串已经是小写字母或者字符串长度不同等,你可以四处玩,看看差异会受到怎样的影响.

无论如何,如果你想让你的代码更"高效",也更清晰,类型安全,不易出错,不要使用字符串来做这样的事情.使用枚举.

卡片组非常适合通过枚举实现,它经常被用来说明这个enum概念:http://docs.oracle.com/javase/8/docs/technotes/guides/language/enums.html#Card


Zie*_*elu 7

您可以自己检查代码(它包含在SDK中).

.equalsIgnoreCase比toUperCase()更快.equals()在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;
Run Code Online (Sandbox Code Playgroud)

因此,如果比较的字符串实际上是不同的,它将比第一次调用UpPaseCase更快,然后等于toUperCase将修改所有字符.此外,toUperCase中涉及的逻辑似乎比比较循环中更复杂,并且它最终会创建一个新的String对象.

但是你需要进行大量的比较操作才能真正看到任何差异.