首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >equalsIgnoreCase()与toUpperCase().equals和toLowerCase().equals的效率

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

Stack Overflow用户
提问于 2015-04-22 08:30:16
回答 3查看 11.2K关注 0票数 15

标题说明了一切。我的问题是关于不同String等价方法的效率。我经常使用.equalsIgnoreCase(String str),因为我对它很有兴趣。但我开始怀疑,这是否不是在Strings之间找到等价物的最有效方法。在我看来,.equalsIgnoreCase(String str)正在调用其中一个大小写转换方法toUpperCasetoLowerCase,然后在其定义中调用equals,但我可能是错的。那么,在以下情况下,或者任何情况下,这些方法中哪一种更有效?

代码语言:javascript
复制
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;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-22 09:08:08

JMH使微基准测试变得简单:

更新:将输入字符串设置为参数,以处理来自JMH上帝Alexey Shipilev的评论。我将目标字符串保留为常量,因为OP的用例是将输入字符串与常量进行比较。

代码语言:javascript
复制
@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();
    }
}

和输出:

代码语言:javascript
复制
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

已使用参数更新输出:

代码语言:javascript
复制
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更快,但除非您每秒执行一百万次比较,否则您不会注意到任何差异。

你可以尝试一下,看看如果第一个字符串已经是小写的,或者如果字符串的长度不同,那么差异会受到怎样的影响。

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

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

票数 17
EN

Stack Overflow用户

发布于 2015-04-22 08:52:39

令人惊讶的是,由于一些奇怪的Unicode原因,这些方法并不等价:

  • toUpperCase("ß")返回"SS" (即两个字母),虽然equalsIgnoreCase works character-wise
  • There是toUpperCasetoLowerCase都不能满足的字符,但您必须同时执行

关于效率,我敢打赌,equalsIgnoreCase要快得多,因为它不会复制任何数据。它还从长度比较开始。

另请注意,toUpperCasetoLowerCaseLocale-sensitive,而equalsIgnoreCase不是。IIRC如果使用异国语言环境,性能会降低。

你的用例

最好和最简单的优化方法是预先对外壳进行标准化。没有理由在你的数据中有“皇后”,“皇后”和"Queen“-尽快清理输入。

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

恐怕,你的循环坏了。在任何一次JQK之后,你跳过一张牌,这是故意的吗?

简化代码

执行以下操作

  • 使用return x;

循环来保持它的整洁,使用局部变量来避免重复复杂的if (x) return true; else return false; by return x;

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

代码语言:javascript
复制
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;
票数 16
EN

Stack Overflow用户

发布于 2015-04-22 08:42:56

您可以自己查看代码(包含在SDK中)。

.equalsIgnoreCase比Java8中的toUperCase().equals()快,代码是:

代码语言:javascript
复制
   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然后调用equals更快,因为toUperCase将修改所有字符。此外,toUperCase中涉及的逻辑似乎比比较循环中的逻辑更复杂,它在最后创建了一个新的String对象。

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

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29785600

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档