प्रदर्शन-वार parseInt
और ऐसे अन्य समाधानों की तुलना में बहुत अधिक खराब हैं, क्योंकि कम से कम अपवाद से निपटने की आवश्यकता होती है।
मैंने jmh परीक्षण चलाए हैं और पाया है कि स्ट्रिंग का उपयोग करके स्ट्रिंग के charAt
साथ तुलना करना और स्ट्रिंग पर केवल अंकों का परीक्षण करना सबसे तेज़ तरीका है।
जेएमएच परीक्षण
टेस्ट Character.isDigit
बनाम Pattern.matcher().matches
बनाम प्रदर्शन की तुलना Long.parseLong
चार मूल्यों की जाँच करते हैं।
इन तरीकों से गैर-एससीआई तार और तार वाले +/- संकेतों के लिए अलग-अलग परिणाम उत्पन्न हो सकते हैं।
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;
}
}
}
}
}
}
23 फरवरी, 2018 को अपडेट किया गया
- दो और मामले जोड़ें - एक
charAt
अतिरिक्त सरणी बनाने के बजाय और IntStream
चार कोड का उपयोग करके
- लूपेड टेस्ट मामलों के लिए गैर-अंक पाए जाने पर तत्काल ब्रेक जोड़ें
- लूपेड परीक्षण मामलों के लिए खाली स्ट्रिंग के लिए गलत लौटें
23 फरवरी, 2018 को अपडेट किया गया
- एक और परीक्षण मामला जोड़ें (सबसे तेज़!) जो स्ट्रीम का उपयोग किए बिना चार मूल्य की तुलना करता है
matches("\\d{2,}")
या तो का उपयोग करेंPattern
और एक के साथ प्रयास करें औरMatcher