it-swarm.com.de

Kürzen Sie ein mögliches Präfix einer Zeichenfolge in Java

Ich habe String str, aus dem ich die Unterzeichenfolge mit einem möglichen Präfix "abc" extrahieren möchte.

Die erste Lösung, die mir einfällt, ist:

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

Meine Fragen sind:

  1. Gibt es eine "sauberere" Möglichkeit, dies mit split und einem regulären Ausdruck für einen "abc" Präfix zu tun?

  2. Wenn ja, ist es weniger effizient als die obige Methode (weil die Zeichenfolge "durchgehend" gesucht wird)?

  3. Wenn ja, gibt es einen besseren Weg (wo "besserer Weg" = saubere und effiziente Lösung ist)?

Bitte beachten Sie, dass das "abc"-Präfix an anderer Stelle in der Zeichenfolge erscheinen kann und nicht entfernt werden sollte.

Vielen Dank

26
barak manos

Kürzer als der obige Code wird diese Zeile sein:

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

Aber in Bezug auf die Leistung, denke ich, gibt es keinen wesentlichen Unterschied zwischen zwei Codes. Man verwendet Regex und man verwendet Regex nicht, sondern führt Such- und Teilzeichenfolgen aus.

36
anubhava

Verwendung von String.replaceFirst mit ^abc (um die führende abc abzugleichen)

"abcdef".replaceFirst("^abc", "")     // => "def"
"123456".replaceFirst("^abc", "")     // => "123456"
"123abc456".replaceFirst("^abc", "")  // => "123abc456"
5
falsetru
  1. Die Verwendung von String#split kann dies, aber es ist keine bessere Lösung. Eigentlich ist es vage und ich würde es nicht empfehlen, es zu diesem Zweck zu verwenden.
  2. Verschwenden Sie in diesem Fall keine Zeit mit Effizienz, es ist nicht wichtig, konzentrieren Sie sich auf Logik und Klarheit. Beachten Sie jedoch, dass die Arbeit mit regex normalerweise langsamer ist, da zusätzliche Operationen erforderlich sind, sodass Sie startsWith beibehalten möchten.
  3. Ihr Ansatz ist gut, wenn Sie überprüfen möchten, ob der String mit "abc" beginnt, und String#startsWith dafür entworfen wurde.

Sie können einfach die Zeit messen, die ein Code zur Ausführung benötigt. Was Sie hier tun können:

Erstellen Sie eine große Schleife, in der Sie den Zähler an einen Dummy-String anhängen können, um die Strings zu simulieren, die Sie prüfen möchten, und versuchen Sie, einmal startsWith und replaceAll nach:

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
1
Maroun

Versuche dies

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

Eine reguläre-freie Lösung (Ich habe dies benötigt, da der zu entfernende String konfigurierbar ist und Backslashes enthält, die für die wörtliche Verwendung in einer Regex umgangen werden müssen):

Apache Commons Lang StringUtils.removeStart(str, remove) entfernt remove vom Start von str mit String.startsWith und String.substring

Der Quellcode der Methode ist informativ:

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;
}
1
mseebach

Wenn Sie über die Leistung besorgt sind, können Sie die str.replaceFirst("^abc", "")-Lösung verbessern, indem Sie dasselbe vorkompilierte Präfix Pattern für das Abgleichen mehrerer Zeichenfolgen verwenden.

final Pattern prefix = Pattern.compile("^abc"); // Could be static constant etc
for ... {
    final String result = prefix.matcher(str).replaceFirst("");
}

Ich denke, der Unterschied wird sich bemerkbar machen, wenn man das gleiche Präfix von vielen Strings entfernt.

0
Sokolov