Лучший метод для сопоставления строковых шаблонов в Java, если производительность является проблемой - PullRequest
1 голос
/ 27 мая 2011

Привет,

Допустим, вы хотели проверить строку, чтобы увидеть, является ли она точным соответствием или, если это совпадение с _ и любым количеством символов, добавленных после _

Примеры правильных совпадений:

MyTestString
MyTestString_
MyTestString_1234

Если бы производительность была огромной проблемой, какие методы вы бы исследовали?В настоящее время я делаю следующее:

if (String.equals(stringToMatch)) {
            // success
        } else {
            if (stringToMatch.contains(stringToMatch + "_")) {
                // success
            }
            // fail
        }

Я пытался заменить шаблон String.contains _ на соответствие Java.util.regex.Pattern для _ *, но это работало намного хуже.Является ли мое решение здесь идеальным или вы можете придумать что-нибудь более умное, чтобы улучшить производительность?

Спасибо за любые мысли

Ответы [ 3 ]

8 голосов
/ 27 мая 2011

Вы можете сделать что-то вроде

if(string.startsWith(testString)) {
    int len = testString.length();
    if(string.length() == len || string.charAt(len) == '_')
          // success
}

Я предполагаю, что вы хотите, чтобы testString появлялся, даже если у вас есть "_"?


РЕДАКТИРОВАТЬ: на, использовать лидлинные условия или вложенные операторы if, нет разницы в коде или производительности.

public static void nestedIf(boolean a, boolean b) {
    if (a) {
        if (b) {
            System.out.println("a && b");
        }
    }
}

public static void logicalConditionIf(boolean a, boolean b) {
    if (a && b) {
        System.out.println("a && b");
    }
}

компилируется в тот же код.Если вы делаете javap -c

public static void nestedIf(boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    16
   4:   iload_1
   5:   ifeq    16
   8:   getstatic       #7; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  ldc     #8; //String a && b
   13:  invokevirtual   #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   16:  return

public static void logicalConditionIf(boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    16
   4:   iload_1
   5:   ifeq    16
   8:   getstatic       #7; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  ldc     #8; //String a && b
   13:  invokevirtual   #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   16:  return

Соответствующий код идентичен.

2 голосов
/ 27 мая 2011

Вы можете использовать регулярные выражения для сопоставления с шаблонами. Вы можете использовать stringToMatch.matches(".*?_.*?"). Это возвращает логическое значение.

1 голос
/ 27 мая 2011

Я провел несколько тестов.Это самое быстрое, что я могу получить.

    String a = "Test123";
    String b = "Test123_321tseT_Test_rest";
    int len1 = a.length();
    int len2 = b.length();
    if ((len1 == len2 || (len2 > len1 && (b.charAt(len1)) == '_'))
        && b.startsWith(a)) {
        System.out.println("success");
    } else {
        System.out.println("Fail");
    }

Это будет, по крайней мере, правильно работать при разумной производительности.

Редактировать: я переключил проверку _ и запуску с проверкой, так как запускается с ухудшениемВыполните проверку _.

Edit2: исправлено исключение StringIndexOutOfBoundsException.

Edit3: Правильно, Питер Лори, который делает только 1 вызов a.length (), экономит время.2,2% в моем случае.Последний тест показывает, что я на 88% быстрее, чем OP, и на 10% быстрее, чем код Питера Лоури.

Edit4: я заменяю все str.length () на локальную переменную var и запускаю еще дюжину тестов.Теперь результаты тестов становятся настолько случайными, что невозможно сказать, какой код быстрее.Моя последняя версия, кажется, выигрывает на ступеньку выше.

...