Подтвердить что ты не робот

Обрезать возможный префикс строки в Java

У меня есть String str, из которого я хочу извлечь подстроку, исключая возможный префикс "abc".

Первое решение, которое приходит на ум:

if (str.startsWith("abc"))
    return str.substring("abc".length());
return str;

Мои вопросы:

  • Существует ли "чистый" способ сделать это с помощью split и регулярного выражения для префикса "abc" ?

  • Если да, то он менее эффективен, чем метод выше (потому что он выполняет поиск по всей строке)?

  • Если да, есть ли лучший способ сделать это (где "лучший способ" = чистое и эффективное решение)?

Обратите внимание, что префикс "abc" может появляться в другом месте строки и не должен быть удален.

Спасибо

4b9b3361

Ответ 1

Короче, чем выше код, будет эта строка:

return str.replaceFirst("^abc", "");

Но с точки зрения производительности я предполагаю, что не будет существенной разницы между двумя кодами. Один использует регулярное выражение и не использует регулярное выражение, но выполняет поиск и подстроку.

Ответ 2

Использование String.replaceFirst с ^abc (для соответствия ведущему abc)

"abcdef".replaceFirst("^abc", "")     // => "def"
"123456".replaceFirst("^abc", "")     // => "123456"
"123abc456".replaceFirst("^abc", "")  // => "123abc456"

Ответ 3

  • Использование String#split может сделать это, но это не лучшее решение. На самом деле это будет неопределенным, и я бы не рекомендовал использовать его для этой цели.
  • Не тратьте время на эффективность в этом случае, это не важно, сосредоточьтесь на логике и ясности. Но обратите внимание, что работа с регулярным выражением обычно медленнее, поскольку она включает дополнительные операции, поэтому вы можете сохранить startsWith.
  • Ваш подход прекрасен, если вы хотите проверить, начинается ли String с "abc", String#startsWith.

Вы можете легко измерить время выполнения кода. Вот что вы можете сделать:

Создайте большой цикл, внутри него вы можете добавить счетчик его в какую-то фиктивную строку, чтобы имитировать строки, которые вы хотите проверить, затем попробуйте startsWith один раз и replaceAll после:

for(int i = 0;i<900000;i++) {
    StringBuilder sb = new StringBuilder("abc");
    sb.append(i);
    if(sb.toString().startsWith("abc")) { ... } 
}
long time = System.currentTimeMillis() - start;
System.out.println(time); //Prints ~130

for(int i = 0;i<900000;i++){
   StringBuilder sb = new StringBuilder("abc");
   sb.append(i);
   sb.toString().replaceAll("^abc", "");        
}
long time = System.currentTimeMillis() - start;
System.out.println(time);  //Prints ~730

Ответ 4

Попробуйте это

str = str.replaceAll("^abc", "");

Ответ 5

Решение, свободное от регулярных выражений (мне это нужно, потому что строка, которую я удаляю, настраивается и содержит обратную косую черту, которая требует ускорения для литералов в регулярном выражении):

Apache Commons Lang StringUtils.removeStart(str, remove) удалит remove с начала str с помощью String.startsWith и String.substring.

исходный код метода информативен:

public static String removeStart(final String str, final String remove) {
    if (isEmpty(str) || isEmpty(remove)) {
        return str;
    }
    if (str.startsWith(remove)){
        return str.substring(remove.length());
    }
    return str;
}

Ответ 6

Что касается эффективности, вы можете использовать StringBuilder, где у вас есть несколько операций над одной строкой, например подстрока, затем поиск индекса, затем подстрока и т.д.


Если речь идет о чистоте/эффективности, можно использовать StringUtils (Apache Commons Lang).

Надеюсь, что это поможет.