Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most efficient way to make the first character of a String lower case?

What is the most efficient way to make the first character of a String lower case?

I can think of a number of ways to do this:

Using charAt() with substring()

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

Or using a char array

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

I am sure there are many other great ways to achieve this. What do you recommend?

like image 836
Andy Avatar asked Oct 29 '10 14:10

Andy


People also ask

How do you lowercase the first letter of a string?

To capitalize the first letter of a string and lowercase the rest, use the charAt() method to access the character at index 0 and capitalize it using the toUpperCase() method. Then concatenate the result with using the slice() method to to lowercase the rest of the string.

How do you make string to lowercase?

JavaScript String toLowerCase() The toLowerCase() method converts a string to lowercase letters. The toLowerCase() method does not change the original string.

How do you make the first letter lowercase in Python?

To convert the first letter of a string to lowercase, you can use string slicing and the Python lower() function. First, we get the first letter of a string and then use the lower() function to make it lowercase.

How do you get the first character of a string as a string?

To get the first and last characters of a string, access the string at the first and last indexes. For example, str[0] returns the first character, whereas str[str. length - 1] returns the last character of the string.


2 Answers

I tested the promising approaches using JMH. Full benchmark code.

Assumption during the tests (to avoid checking the corner cases every time): the input String length is always greater than 1.

Results

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 

The score are operations per second, the more the better.

Tests

  1. test1 was first Andy's and Hllink's approach:

    string = Character.toLowerCase(string.charAt(0)) + string.substring(1); 
  2. test2 was second Andy's approach. It is also Introspector.decapitalize() suggested by Daniel, but without two if statements. First if was removed because of the testing assumption. The second one was removed, because it was violating correctness (i.e. input "HI" would return "HI"). This was almost the fastest.

    char c[] = string.toCharArray(); c[0] = Character.toLowerCase(c[0]); string = new String(c); 
  3. test3 was a modification of test2, but instead of Character.toLowerCase(), I was adding 32, which works correctly if and only if the string is in ASCII. This was the fastest. c[0] |= ' ' from Mike's comment gave the same performance.

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

    StringBuilder sb = new StringBuilder(string); sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); string = sb.toString(); 
  5. test5 used two substring() calls.

    string = string.substring(0, 1).toLowerCase() + string.substring(1); 
  6. test6 uses reflection to change char value[] directly in String. This was the slowest.

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

Conclusions

If the String length is always greater than 0, use test2.

If not, we have to check the corner cases:

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

If you are sure that your text will be always in ASCII and you are looking for extreme performance because you found this code in the bottleneck, use test3.

like image 112
Adam Stelmaszczyk Avatar answered Sep 19 '22 14:09

Adam Stelmaszczyk


I came across a nice alternative if you don't want to use a third-party library:

import java.beans.Introspector;  Assert.assertEquals("someInputString", Introspector.decapitalize("SomeInputString")); 
like image 43
Daniel Pacak Avatar answered Sep 19 '22 14:09

Daniel Pacak