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

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

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

使用charAt()substring()

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

或者使用一个char数组

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

我相信还有很多其他很好的方法来实现这一点。 你有什么build议?

我testing了使用JMH的有前景的方法。 完整的基准代码 。

testing过程中的假设(避免每次检查angular落情况):input的string长度总是大于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 

得分是每秒操作,越多越好。

testing

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

     string = Character.toLowerCase(string.charAt(0)) + string.substring(1); 
  2. test2是安迪的第二个方法。 它也是Daniel提出的Introspector.decapitalize() ,但没有两个if语句。 首先, if因为testing假设而被删除。 第二个被删除,因为它违反了正确性(即input"HI"将返回"HI" )。 这几乎是最快的。

     char c[] = string.toCharArray(); c[0] = Character.toLowerCase(c[0]); string = new String(c); 
  3. test3test2一个修改,但不是Character.toLowerCase() ,我添加了32,只有当string是ASCII时,它才能正常工作。 这是最快的。 Mike的评论中的 c[0] |= ' 'performance相同。

     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使用reflection来直接在String中改变char value[] 。 这是最慢的。

     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(); } 

结论

如果string长度总是大于0,请使用test2

如果没有,我们必须检查angular落案件:

 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

如果你不想使用第三方库,我遇到了一个很好的select:

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

当涉及到string操作看看雅加达共享Lang StringUtils 。

尽pipe面向字符的方法,我会build议一个面向string的解决scheme String.toLowerCase是特定于语言环境的,所以我会考虑这个问题。 String.toLowerCase更喜欢根据Character.toLowerCase进行小写。 另外一个面向字符的解决scheme不是完全的Unicode兼容,因为Character.toLowerCase不能处理补充字符。

 public static final String uncapitalize(final String originalStr, final Locale locale) { final int splitIndex = 1; final String result; if (originalStr.isEmpty()) { result = originalStr; } else { final String first = originalStr.substring(0, splitIndex).toLowerCase( locale); final String rest = originalStr.substring(splitIndex); final StringBuilder uncapStr = new StringBuilder(first).append(rest); result = uncapStr.toString(); } return result; } 

更新:作为一个例子,区域设置的重要性让我们小写土耳其语和德语:

 System.out.println(uncapitalize("I", new Locale("TR","tr"))); System.out.println(uncapitalize("I", new Locale("DE","de"))); 

会输出两个不同的结果:

一世

一世

如果您想使用Apache Commons,您可以执行以下操作:

 import org.apache.commons.lang3.text.WordUtils; [...] String s = "SomeString"; String firstLower = WordUtils.uncapitalize(s); 

结果:someString

Java中的string是不可变的,所以无论如何一个新的string将被创build。

你的第一个例子可能会稍微有效,因为它只需要创build一个新的string,而不是一个临时的字符数组。

如果你需要的是非常简单的(例如,java类名,没有语言环境),你也可以使用Google Guava库中的CaseFormat类。

 String converted = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, "FooBar"); assertEquals("fooBar", converted); 

或者你可以准备和重用一个转换器对象,这可能会更有效率。

 Converter<String, String> converter= CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL); assertEquals("fooBar", converter.convert("FooBar")); 

为了更好地理解Google Guavastring操作的哲学,请查看这个wiki页面 。

一个非常简短的静态方法来存档你想要的:

 public static String decapitalizeString(String string) { return string == null || string.isEmpty() ? "" : Character.toLowerCase(string.charAt(0)) + string.substring(1); } 
 String testString = "SomeInputString"; String firstLetter = testString.substring(0,1).toLowerCase(); String restLetters = testString.substring(1); String resultString = firstLetter + restLetters; 

我今天才知道这件事。 试图以最行人的方式自己做。 那只有一条线,寿命长。 开始

 String str = "TaxoRank"; System.out.println(" Before str = " + str); str = str.replaceFirst(str.substring(0,1), str.substring(0,1).toLowerCase()); System.out.println(" After str = " + str); 

得到:

在str = TaxoRanks之前

在str = taxoRanks之后