2008-09-18 15 views

Respuesta

22

Solo marcando si una letra está en A-Z porque eso no incluye letras con acentos o letras en otros alfabetos.

descubrí que se puede utilizar la clase de expresiones regulares para la 'letra Unicode', o una de sus variantes mayúsculas y minúsculas:

string.matches("\\p{L}"); // Unicode letter 
string.matches("\\p{Lu}"); // Unicode upper-case letter 

También puede hacer esto con carácter de clase:

Character.isLetter(character); 

pero eso es menos conveniente si necesita comprobar más de una letra.

33

Character.isLetter() es mucho más rápido que string.matches(), porque string.matches() compila un nuevo patrón cada vez. Incluso guardando en caché el patrón, creo que Letter() todavía lo superaría.


EDIT: acaba de ejecutar a través de este nuevo y pensé que iba a tratar de llegar a algunos números reales. Aquí está mi intento de un punto de referencia, comprobando los tres métodos (matches() con y sin almacenar en caché el Pattern y Character.isLetter()). También me aseguré de que se verificaran los caracteres válidos y no válidos, para no sesgar las cosas.

import java.util.regex.*; 

class TestLetter { 
    private static final Pattern ONE_CHAR_PATTERN = Pattern.compile("\\p{L}"); 
    private static final int NUM_TESTS = 10000000; 

    public static void main(String[] args) { 
     long start = System.nanoTime(); 
     int counter = 0; 
     for (int i = 0; i < NUM_TESTS; i++) { 
      if (testMatches(Character.toString((char) (i % 128)))) 
       counter++; 
     } 
     System.out.println(NUM_TESTS + " tests of Pattern.matches() took " + 
       (System.nanoTime()-start) + " ns."); 
     System.out.println("There were " + counter + "/" + NUM_TESTS + 
       " valid characters"); 
     /*********************************/ 
     start = System.nanoTime(); 
     counter = 0; 
     for (int i = 0; i < NUM_TESTS; i++) { 
      if (testCharacter(Character.toString((char) (i % 128)))) 
       counter++; 
     } 
     System.out.println(NUM_TESTS + " tests of isLetter() took " + 
       (System.nanoTime()-start) + " ns."); 
     System.out.println("There were " + counter + "/" + NUM_TESTS + 
       " valid characters"); 
     /*********************************/ 
     start = System.nanoTime(); 
     counter = 0; 
     for (int i = 0; i < NUM_TESTS; i++) { 
      if (testMatchesNoCache(Character.toString((char) (i % 128)))) 
       counter++; 
     } 
     System.out.println(NUM_TESTS + " tests of String.matches() took " + 
       (System.nanoTime()-start) + " ns."); 
     System.out.println("There were " + counter + "/" + NUM_TESTS + 
       " valid characters"); 
    } 

    private static boolean testMatches(final String c) { 
     return ONE_CHAR_PATTERN.matcher(c).matches(); 
    } 
    private static boolean testMatchesNoCache(final String c) { 
     return c.matches("\\p{L}"); 
    } 
    private static boolean testCharacter(final String c) { 
     return Character.isLetter(c.charAt(0)); 
    } 
} 

Y mi salida:

10000000 tests of Pattern.matches() took 4325146672 ns. 
There were 4062500/10000000 valid characters 
10000000 tests of isLetter() took 546031201 ns. 
There were 4062500/10000000 valid characters 
10000000 tests of String.matches() took 11900205444 ns. 
There were 4062500/10000000 valid characters

Así que eso es casi 8 veces mejor, incluso con un caché Pattern. (Y sin caché es casi 3 veces peor que en caché.)

+3

Debe usar 'c.codePointAt (0)' en lugar de 'c.charAt (0)' en 'testCharacter()'; de lo contrario, fallará para los caracteres fuera del BMP. –

Cuestiones relacionadas