parseInt
최소한 예외 처리가 필요하기 때문에 성능 측면 에서는 다른 솔루션보다 훨씬 나쁩니다.
jmh 테스트를 실행했으며 문자열을 사용하여 문자열을 반복하고 charAt
문자를 경계 문자와 비교하는 것이 문자열에 숫자 만 포함되어 있는지 테스트하는 가장 빠른 방법 이라는 것을 알았습니다 .
JMH 테스트
테스트는 char 값 과 vs. char 값의 성능을 Character.isDigit
비교 합니다.Pattern.matcher().matches
Long.parseLong
이러한 방식은 ASCII가 아닌 문자열과 +/- 기호가 포함 된 문자열에 대해 다른 결과를 생성 할 수 있습니다.
테스트 는 5 번의 워밍업 반복과 5 번의 테스트 반복 으로 처리량 모드에서 실행됩니다 ( 더 클수록 좋습니다 ).
결과
주 parseLong
에 비해 거의 100 배 느린 isDigit
첫 번째 테스트 부하.
## Test load with 25% valid strings (75% strings contain non-digit symbols)
Benchmark Mode Cnt Score Error Units
testIsDigit thrpt 5 9.275 ± 2.348 ops/s
testPattern thrpt 5 2.135 ± 0.697 ops/s
testParseLong thrpt 5 0.166 ± 0.021 ops/s
## Test load with 50% valid strings (50% strings contain non-digit symbols)
Benchmark Mode Cnt Score Error Units
testCharBetween thrpt 5 16.773 ± 0.401 ops/s
testCharAtIsDigit thrpt 5 8.917 ± 0.767 ops/s
testCharArrayIsDigit thrpt 5 6.553 ± 0.425 ops/s
testPattern thrpt 5 1.287 ± 0.057 ops/s
testIntStreamCodes thrpt 5 0.966 ± 0.051 ops/s
testParseLong thrpt 5 0.174 ± 0.013 ops/s
testParseInt thrpt 5 0.078 ± 0.001 ops/s
테스트 스위트
@State(Scope.Benchmark)
public class StringIsNumberBenchmark {
private static final long CYCLES = 1_000_000L;
private static final String[] STRINGS = {"12345678901","98765432177","58745896328","35741596328", "123456789a1", "1a345678901", "1234567890 "};
private static final Pattern PATTERN = Pattern.compile("\\d+");
@Benchmark
public void testPattern() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
b = PATTERN.matcher(s).matches();
}
}
}
@Benchmark
public void testParseLong() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
try {
Long.parseLong(s);
b = true;
} catch (NumberFormatException e) {
// no-op
}
}
}
}
@Benchmark
public void testCharArrayIsDigit() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (char c : s.toCharArray()) {
b = Character.isDigit(c);
if (!b) {
break;
}
}
}
}
}
@Benchmark
public void testCharAtIsDigit() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (int j = 0; j < s.length(); j++) {
b = Character.isDigit(s.charAt(j));
if (!b) {
break;
}
}
}
}
}
@Benchmark
public void testIntStreamCodes() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
b = s.chars().allMatch(c -> c > 47 && c < 58);
}
}
}
@Benchmark
public void testCharBetween() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (int j = 0; j < s.length(); j++) {
char charr = s.charAt(j);
b = '0' <= charr && charr <= '9';
if (!b) {
break;
}
}
}
}
}
}
2018 년 2 월 23 일에 업데이트 됨
- 추가
charAt
배열을 만드는 대신 사용 IntStream
하고 문자 코드를 사용 하는 경우를 두 개 더 추가하십시오.
- 반복 테스트 사례에 대해 숫자가 아닌 숫자가 발견되면 즉시 중단 추가
- 반복 테스트 사례의 빈 문자열에 대해서는 false를 반환
2018 년 2 월 23 일에 업데이트 됨
- 스트림을 사용하지 않고 문자 값을 비교하는 테스트 케이스를 하나 더 추가하십시오 (가장 빠름).
matches("\\d{2,}")
또는 함께 노력Pattern
하고Matcher