Solo por diversión, he ejecutado este micro benchmark. Los resultados de la última ejecución (es decirJVM después de calentamiento/JIT) están por debajo (los resultados son bastante consistentes de una carrera a otra de todos modos):
regex with numbers 123
chars with numbers 33
parseInt with numbers 33
regex with words 123
chars with words 34
parseInt with words 733
En otras palabras, caracteres es muy eficiente, Integer.parseInt es tan eficiente como char si la cadena es un número, pero muy lento si la cadena no es un número. Regex está en el medio.
Conclusión
Si analizar una cadena en un número y se espera que la cadena a ser un número en general, utilizando Integer.parseInt es la mejor solución (eficiente y legible). La penalización que recibe cuando la cuerda no es un número debe ser baja si no es demasiado frecuente.
ps: mi expresión regular quizás no sea óptima, no dude en comentar.
public class TestNumber {
private final static List<String> numbers = new ArrayList<>();
private final static List<String> words = new ArrayList<>();
public static void main(String args[]) {
long start, end;
Random random = new Random();
for (int i = 0; i < 1000000; i++) {
numbers.add(String.valueOf(i));
words.add(String.valueOf(i) + "x");
}
for (int i = 0; i < 5; i++) {
start = System.nanoTime();
regex(numbers);
System.out.println("regex with numbers " + (System.nanoTime() - start)/1000000);
start = System.nanoTime();
chars(numbers);
System.out.println("chars with numbers " + (System.nanoTime() - start)/1000000);
start = System.nanoTime();
exception(numbers);
System.out.println("exceptions with numbers " + (System.nanoTime() - start)/1000000);
start = System.nanoTime();
regex(words);
System.out.println("regex with words " + (System.nanoTime() - start)/1000000);
start = System.nanoTime();
chars(words);
System.out.println("chars with words " + (System.nanoTime() - start)/1000000);
start = System.nanoTime();
exception(words);
System.out.println("exceptions with words " + (System.nanoTime() - start)/1000000);
}
}
private static int regex(List<String> list) {
int sum = 0;
Pattern p = Pattern.compile("[0-9]+");
for (String s : list) {
sum += (p.matcher(s).matches() ? 1 : 0);
}
return sum;
}
private static int chars(List<String> list) {
int sum = 0;
for (String s : list) {
boolean isNumber = true;
for (char c : s.toCharArray()) {
if (c < '0' || c > '9') {
isNumber = false;
break;
}
}
if (isNumber) {
sum++;
}
}
return sum;
}
private static int exception(List<String> list) {
int sum = 0;
for (String s : list) {
try {
Integer.parseInt(s);
sum++;
} catch (NumberFormatException e) {
}
}
return sum;
}
}
Forma simple de averiguarlo: ejecuta ambas opciones y cronometra cada una. El proceso está vinculado a la CPU, por lo que la duración le indicará cuál es más eficiente. Tenga en cuenta que puede hacer que la expresión regular sea más eficiente reutilizando el patrón compilado, en lugar de utilizar 'string.matches()', que vuelve a compilar la expresión regular en cada llamada. – Bohemian