用Java替换String的第一个字母?

时间:2010-03-15 13:31:45

标签: java string

我正在尝试将字符串的第一个字母转换为小写。

value.substring(0,1).toLowerCase() + value.substring(1)

这有效,但还有更好的方法吗?

我可以使用替换函数,但Java的替换不接受索引。您必须传递实际的字符/子字符串。可以这样做:

value.replaceFirst(value.charAt(0), value.charAt(0).toLowerCase())

除了replaceFirst需要2个字符串,因此value.charAt(0)可能需要替换为value.substring(0,1)

有没有标准的方法来替换String的第一个字母?

4 个答案:

答案 0 :(得分:12)

我建议你看一下Apache的Commons-Lang库。他们有一个班级

StringUtils

允许您使用字符串执行大量任务。在您的情况下,只需使用

StringUtils.uncapitalize( value )

read here about uncapitalize以及建议的其他功能

已添加:我的经验告诉我,Coomon-Lang已经过很好的优化,所以如果想从算法的角度来看想知道什么更好,你可以看一下Apache的来源。 / p>

答案 1 :(得分:3)

你使用的代码(我在类似的情况下使用过)的缺点是,它看起来有点笨拙,理论上会生成至少两个立即被丢弃的临时字符串。如果您的字符串长度少于两个字符,还会出现问题。

好处是你没有引用表达式之外的那些临时字符串(通过字节码编译器或JIT优化器让它开放优化),你的意图对任何未来的代码维护者都很清楚。

除非您需要在任何给定的第二个检测到明显的性能问题中执行数百万次这样的操作,否则我不会担心性能,而是希望清晰度。我也会把它埋在某处的实用工具中。 :-)另见jambjo对另一个答案的回答,指出String#toLowerCaseCharacter.toLowerCase之间存在重要差异。 (编辑:答案和评论已被删除。基本上,与语言环境和Unicode相关的差异很大,文档建议使用String#toLowerCase,而不是Character.toLowerCase; more here

编辑因为我的心情很奇怪,我想我会看到在一个简单的测试中是否存在可测量的性能差异。有。可能是因为区域设置不同(例如,苹果与橙子):

public class Uncap
{
    public static final void main(String[] params)
    {
        String  s;
        String  s2;
        long    start;
        long    end;
        int     counter;

        // Warm up
        s = "Testing";
        start = System.currentTimeMillis();
        for (counter = 1000000; counter > 0; --counter)
        {
            s2 = uncap1(s);
            s2 = uncap2(s);
            s2 = uncap3(s);
        }

        // Test v2
        start = System.currentTimeMillis();
        for (counter = 1000000; counter > 0; --counter)
        {
            s2 = uncap2(s);
        }
        end = System.currentTimeMillis();
        System.out.println("2: " + (end - start));

        // Test v1
        start = System.currentTimeMillis();
        for (counter = 1000000; counter > 0; --counter)
        {
            s2 = uncap1(s);
        }
        end = System.currentTimeMillis();
        System.out.println("1: " + (end - start));

        // Test v3
        start = System.currentTimeMillis();
        for (counter = 1000000; counter > 0; --counter)
        {
            s2 = uncap3(s);
        }
        end = System.currentTimeMillis();
        System.out.println("3: " + (end - start));

        System.exit(0);
    }

    // The simple, direct version; also allows the library to handle
    // locales and Unicode correctly
    private static final String uncap1(String s)
    {
        return s.substring(0,1).toLowerCase() + s.substring(1);
    }

    // This will *not* handle locales and unicode correctly
    private static final String uncap2(String s)
    {
        return Character.toLowerCase(s.charAt(0)) + s.substring(1);
    }

    // This will *not* handle locales and unicode correctly
    private static final String uncap3(String s)
    {
        StringBuffer sb;

        sb = new StringBuffer(s);
        sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
        return sb.toString();
    }
}

我在各种测试中混合了订单(移动它们并重新编译)以避免加速时间问题(并且最初尝试强制一些)。非常不科学,但uncap1始终比uncap2uncap3慢了约40%。并非如此重要,我们谈论的是英特尔凌动处理器上百万次迭代中400毫秒的差异。 : - )

所以:我会使用简单,直接的代码,包含在实用功能中。

答案 2 :(得分:1)

注意字符串中的任何字符函数。由于unicode,它并不总是1对1的映射。坚持使用基于字符串的方法,除非char真的是你想要的。正如其他人所建议的,那里有字符串工具,但即使你不想在项目中使用它们,也可以在工作时自己制作一个。你可以做的最糟糕的事情是为小写创建一个特殊的函数并将其隐藏在一个类中,然后在12个不同的地方使用相同的代码略有不同。把它放在一个可以轻松分享的地方。

答案 3 :(得分:1)

使用StringBuffer

buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));