使字符串的第一个字符小写的最有效方法?

2022-08-31 09:03:32

制作小写字母的第一个字符的最有效方法是什么?String

我可以想出很多方法来做到这一点:

charAt()substring() 一起使用

String input   = "SomeInputString";
String output  = Character.toLowerCase(input.charAt(0)) +
                   (input.length() > 1 ? input.substring(1) : "");

或者使用字符数组

 String input  = "SomeInputString";
 char c[]      = input.toCharArray();
 c[0]          = Character.toLowerCase(c[0]);
 String output = new String(c);

我相信还有许多其他好方法可以实现这一目标。你有什么建议?


答案 1

我使用JMH测试了有前途的方法。完整的基准测试代码

测试期间的假设(以避免每次都检查角情况):输入字符串长度始终大于 1。

结果

Benchmark           Mode  Cnt         Score        Error  Units
MyBenchmark.test1  thrpt   20  10463220.493 ± 288805.068  ops/s
MyBenchmark.test2  thrpt   20  14730158.709 ± 530444.444  ops/s
MyBenchmark.test3  thrpt   20  16079551.751 ±  56884.357  ops/s
MyBenchmark.test4  thrpt   20   9762578.446 ± 584316.582  ops/s
MyBenchmark.test5  thrpt   20   6093216.066 ± 180062.872  ops/s
MyBenchmark.test6  thrpt   20   2104102.578 ±  18705.805  ops/s

分数是每秒的操作数,越多越好。

测试

  1. test1首先是Andy和Hllink的方法:

    string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
    
  2. test2这是安迪的第二种方法。它也是丹尼尔建议的Interspector.deccaptalize(),但没有两个语句。由于测试假设,第一个被删除了。第二个被删除了,因为它违反了正确性(即输入将返回)。这几乎是最快的。ifif"HI""HI"

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);
    string = new String(c);
    
  3. test3是 的修改,但不是 ,我添加了 32,当且仅当字符串采用 ASCII 时,它才能正常工作。这是最快的。 从迈克的评论中给出了相同的表现。test2Character.toLowerCase()c[0] |= ' '

    char c[] = string.toCharArray();
    c[0] += 32;
    string = new String(c);
    
  4. test4使用。StringBuilder

    StringBuilder sb = new StringBuilder(string);
    sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
    string = sb.toString();
    
  5. test5使用了两个调用。substring()

    string = string.substring(0, 1).toLowerCase() + string.substring(1);
    
  6. test6使用反射直接在字符串中更改 char 值 []。这是最慢的。

    try {
        Field field = String.class.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(string);
        value[0] = Character.toLowerCase(value[0]);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    

结论

如果字符串长度始终大于 0,请使用 。test2

如果没有,我们必须检查角落情况:

public static String decapitalize(String string) {
    if (string == null || string.length() == 0) {
        return string;
    }

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);

    return new String(c);
}

如果您确定文本将始终采用 ASCII 格式,并且由于在瓶颈中发现了此代码,因此正在寻找极致的性能,请使用 。test3


答案 2

如果您不想使用第三方库,我遇到了一个不错的选择:

import java.beans.Introspector;

Assert.assertEquals("someInputString", Introspector.decapitalize("SomeInputString"));