Почему все стремятся к решениям исключений / регулярных выражений?
Хотя я понимаю, что большинству людей хорошо использовать try / catch, но если вы хотите делать это часто ... это может быть очень сложным.
Что я сделал здесь, так это возьмем регулярное выражение, методы parseNumber () и метод поиска в массиве, чтобы увидеть, какой из них наиболее эффективен. На этот раз я посмотрел только на целые числа.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
int index = 0;
if (data[0] == '-' && data.length > 1)
index = 1;
for (; index < data.length; index++) {
if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Результаты по скорости, которые я получил, были:
Done with: for (int i = 0; i < 10000000; i++)...
With only valid numbers ("59815833" and "-59815833"):
Array numeric took 395.808192 ms [39.5808192 ns each]
Regex took 2609.262595 ms [260.9262595 ns each]
Exception numeric took 428.050207 ms [42.8050207 ns each]
// Negative sign
Array numeric took 355.788273 ms [35.5788273 ns each]
Regex took 2746.278466 ms [274.6278466 ns each]
Exception numeric took 518.989902 ms [51.8989902 ns each]
// Single value ("1")
Array numeric took 317.861267 ms [31.7861267 ns each]
Regex took 2505.313201 ms [250.5313201 ns each]
Exception numeric took 239.956955 ms [23.9956955 ns each]
// With Character.isDigit()
Array numeric took 400.734616 ms [40.0734616 ns each]
Regex took 2663.052417 ms [266.3052417 ns each]
Exception numeric took 401.235906 ms [40.1235906 ns each]
With invalid characters ("5981a5833" and "a"):
Array numeric took 343.205793 ms [34.3205793 ns each]
Regex took 2608.739933 ms [260.8739933 ns each]
Exception numeric took 7317.201775 ms [731.7201775 ns each]
// With a single character ("a")
Array numeric took 291.695519 ms [29.1695519 ns each]
Regex took 2287.25378 ms [228.725378 ns each]
Exception numeric took 7095.969481 ms [709.5969481 ns each]
With null:
Array numeric took 214.663834 ms [21.4663834 ns each]
Regex took 201.395992 ms [20.1395992 ns each]
Exception numeric took 233.049327 ms [23.3049327 ns each]
Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
Отказ от ответственности: я не утверждаю, что эти методы оптимизированы на 100%, они просто для демонстрации данных
Исключения выигрывают тогда и только тогда, когда число составляет 4 символа или менее, а каждая строка всегда число ... в таком случае, зачем вообще чек?
Короче говоря, это очень больно, если вы часто сталкиваетесь с недопустимыми числами с помощью try / catch, что имеет смысл. Важное правило, которому я всегда следую, это НИКОГДА не использовать try / catch для выполнения программы . Это пример почему.
Интересно, что простой if char <0 || > 9 было чрезвычайно просто написать, легко запомнить (и должно работать на нескольких языках) и выигрывает почти во всех тестовых сценариях.
Единственным недостатком является то, что я предполагаю, что Integer.parseInt () может обрабатывать числа не ASCII, в то время как метод поиска по массиву не делает.
Для тех, кто задается вопросом, почему я сказал, что легко запомнить массив символов, если вы знаете, что нет отрицательных признаков, вы можете легко сойтись с чем-то сжатым, как это:
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
И, наконец, в заключение, мне было любопытно, что оператор присваивания в принятом примере набрал все голоса. Добавление в присвоение
double d = Double.parseDouble(...)
не только бесполезен, поскольку вы даже не используете это значение, но он тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к увеличению времени тестирования на 100-200 мс). Я не понимаю, почему кто-то так поступил, потому что это дополнительная работа по снижению производительности.
Можно подумать, что это будет оптимизировано ... хотя, возможно, мне следует проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда показывался мне более длинным, хотя, если он каким-то образом оптимизирован ... поэтому мне интересно, что происходит. Примечание: под продолжительностью я подразумеваю запуск теста для 10000000 итераций, и запуск этой программы несколько раз (10x +) всегда показывал, что он медленнее.
РЕДАКТИРОВАТЬ: Обновлен тест для Character.isDigit ()