2012-10-11 38 views
13

¿Cuál es la forma más rápida de comprobar que una cadena contiene solo caracteres alfanuméricos?La forma más rápida de comprobar una cadena es alfanumérica en Java

Tengo un código que masticará una gran cantidad de CPU y me pregunto si va a haber una manera más rápida que usar expresiones regulares precompiladas.

ACTUALIZACIÓN: ¿Cuántos votos, cuidado de explicar? Stackoverflow no debe usarse para analizar qué algoritmo usar para lograr una tarea podría ser más rápido.

+1

Nosotros no podemos decir cómo escribir código más rápido que algo que no nos va a mostrar ... –

+1

optimización prematura? ¿Punto de referencia? Perfil? –

+1

@StephenC No hay código para mostrar, estoy preguntando cuál es la mejor manera. – Jacob

Respuesta

16

He escrito las pruebas que verifican la respuesta "correcta". Pruebas realizadas en una máquina con cuatro núcleos OSX10.8 ejecutando Java 1.6

Curiosamente, el uso de expresiones regulares resulta ser unas 5-10 veces más lento que iterar manualmente sobre una cadena. Además, la función isAlphanumeric2() es ligeramente más rápida que isAlphanumeric().

public class QuickTest extends TestCase { 

    private final int reps = 1000000; 

    public void testRegexp() { 
     for(int i = 0; i < reps; i++) 
      ("ab4r3rgf"+i).matches("[a-zA-Z0-9]"); 
    } 

public void testIsAlphanumeric() { 
    for(int i = 0; i < reps; i++) 
     isAlphanumeric("ab4r3rgf"+i); 
} 

public void testIsAlphanumeric2() { 
    for(int i = 0; i < reps; i++) 
     isAlphanumeric2("ab4r3rgf"+i); 
} 

    public boolean isAlphanumeric(String str) { 
     for (int i=0; i<str.length(); i++) { 
      char c = str.charAt(i); 
      if (!Character.isDigit(c) && !Character.isLetter(c)) 
       return false; 
     } 

     return true; 
    } 

    public boolean isAlphanumeric2(String str) { 
     for (int i=0; i<str.length(); i++) { 
      char c = str.charAt(i); 
      if (c < 0x30 || (c >= 0x3a && c <= 0x40) || (c > 0x5a && c <= 0x60) || c > 0x7a) 
       return false; 
     } 
     return true; 
    } 

} 
24

Uso String.matches(), como:

String myString = "qwerty123456"; 
System.out.println(myString.matches("[A-Za-z0-9]+")); 

que puede no ser posible el enfoque "más rápido" absoluta. Pero, en general, no tiene mucho sentido tratar de competir con las personas que escriben la "biblioteca estándar" del idioma en términos de rendimiento.

+0

Sí. C# tiene una función estándar para esto. Parece que Java no. – Jacob

2

Un regex probablemente sea bastante eficiente, ya que especificaría rangos: [0-9a-zA-Z]. Suponiendo que el código de implementación para expresiones regulares es eficiente, esto simplemente requeriría una comparación de límite superior e inferior para cada rango. Aquí es básicamente lo que una expresión regular compilada debe hacer:

boolean isAlphanumeric(String str) { 
    for (int i=0; i<str.length(); i++) { 
     char c = str.charAt(i); 
     if (c < 0x30 || (c >= 0x3a && c <= 0x40) || (c > 0x5a && c <= 0x60) || c > 0x7a) 
      return false; 
    } 

    return true; 
} 

no veo cómo su código podría ser más eficiente que esto, porque tendrá que ser controlado antes de cada carácter, y las comparaciones en realidad no podía ser más sencillo .

+1

Posiblemente va a estar entre esto y 'String.matches()'. Esperaba que alguien lo hubiera hecho antes. Parece que tendré que escribir la prueba yo mismo (: – Jacob

Cuestiones relacionadas