Tôi đã thử nghiệm các cách tiếp cận đầy hứa hẹn bằng cách sử dụng JMH . Mã điểm chuẩn đầy đủ .
Giả định trong quá trình kiểm tra (để tránh kiểm tra các trường hợp góc mỗi lần): độ dài chuỗi đầu vào luôn lớn hơn 1.
Các kết quả
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
Điểm số là hoạt động trên giây, càng nhiều càng tốt.
Kiểm tra
test1
đầu tiên là cách tiếp cận của Andy và Hllink:
string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
test2
là cách tiếp cận thứ hai của Andy. Nó cũng được Introspector.decapitalize()
gợi ý bởi Daniel, nhưng không có hai if
tuyên bố. Đầu tiên if
đã bị loại bỏ vì giả định thử nghiệm. Cái thứ hai đã bị xóa vì nó vi phạm tính đúng đắn (tức là đầu vào "HI"
sẽ trả về "HI"
). Đây gần như là nhanh nhất.
char c[] = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
string = new String(c);
test3
là một sửa đổi của test2
, nhưng thay vì Character.toLowerCase()
, tôi đã thêm 32, hoạt động chính xác nếu và chỉ khi chuỗi nằm trong ASCII. Đây là nhanh nhất. c[0] |= ' '
từ bình luận của Mike đã cho hiệu suất tương tự.
char c[] = string.toCharArray();
c[0] += 32;
string = new String(c);
test4
đã qua sử dụng StringBuilder
.
StringBuilder sb = new StringBuilder(string);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
string = sb.toString();
test5
đã sử dụng hai substring()
cuộc gọi.
string = string.substring(0, 1).toLowerCase() + string.substring(1);
test6
sử dụng phản chiếu để thay đổi char value[]
trực tiếp trong Chuỗi. Đây là chậm nhất.
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();
}
Kết luận
Nếu độ dài Chuỗi luôn lớn hơn 0, hãy sử dụng test2
.
Nếu không, chúng tôi phải kiểm tra các trường hợp góc:
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);
}
Nếu bạn chắc chắn rằng văn bản của bạn sẽ luôn ở trong ASCII và bạn đang tìm kiếm hiệu suất cực cao vì bạn đã tìm thấy mã này trong nút cổ chai, hãy sử dụng test3
.