Auswertung der Hauptantworten mit einem Leistungsbenchmark, der Bedenken bestätigt, dass die aktuell gewählte Antwort kostspielige Regex-Operationen unter der Haube macht
Bisher gibt es die drei Antworten in drei Hauptstilen (ohne Berücksichtigung der JavaScript-Antwort;)):
- Verwenden Sie String.replace (charsToDelete, ""); welches Regex unter der Haube verwendet
- Verwenden Sie Lambda
- Verwenden Sie eine einfache Java-Implementierung
In Bezug auf die Codegröße ist der String.replace eindeutig der knappste. Die einfache Java-Implementierung ist etwas kleiner und sauberer (IMHO) als die Lambda (verstehen Sie mich nicht falsch - ich verwende Lambdas oft dort, wo sie angemessen sind).
Die Ausführungsgeschwindigkeit war in der Reihenfolge der schnellsten bis langsamsten: einfache Java-Implementierung, Lambda und dann String.replace () (der Regex aufruft).
Die mit Abstand schnellste Implementierung war die einfache Java-Implementierung, die so abgestimmt wurde, dass sie den StringBuilder-Puffer auf die maximal mögliche Ergebnislänge vorbelegt und dann einfach Zeichen an den Puffer anfügt, die nicht in der Zeichenfolge "Zeichen zum Löschen" enthalten sind. Dadurch werden Neuzuweisungen vermieden, die für Zeichenfolgen mit einer Länge von> 16 Zeichen auftreten würden (die Standardzuweisung für StringBuilder), und es wird vermieden, dass beim Löschen von Zeichen aus einer Kopie der Zeichenfolge, die auftritt, die Lambda-Implementierung auftritt.
Der folgende Code führt einen einfachen Benchmark-Test durch, bei dem jede Implementierung 1.000.000 Mal ausgeführt und die verstrichene Zeit protokolliert wird.
Die genauen Ergebnisse variieren mit jedem Lauf, aber die Reihenfolge der Leistung ändert sich nie:
Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms
Die Lambda-Implementierung (wie aus Kaplans Antwort kopiert) ist möglicherweise langsamer, da sie eine "Verschiebung um eins um eins" aller Zeichen nach rechts von dem zu löschenden Zeichen ausführt. Dies würde sich offensichtlich bei längeren Zeichenfolgen mit vielen zu löschenden Zeichen verschlechtern. Außerdem kann die Lambda-Implementierung selbst einen gewissen Overhead verursachen.
Die String.replace-Implementierung verwendet Regex und führt bei jedem Aufruf eine Regex-Kompilierung durch. Eine Optimierung hierfür wäre, Regex direkt zu verwenden und das kompilierte Muster zwischenzuspeichern, um die Kosten für die Kompilierung jedes Mal zu vermeiden.
package com.sample;
import java.util.function.BiFunction;
import java.util.stream.IntStream;
public class Main {
static public String deleteCharsSimple(String fromString, String charsToDelete)
{
StringBuilder buf = new StringBuilder(fromString.length()); // Preallocate to max possible result length
for(int i = 0; i < fromString.length(); i++)
if (charsToDelete.indexOf(fromString.charAt(i)) < 0)
buf.append(fromString.charAt(i)); // char not in chars to delete so add it
return buf.toString();
}
static public String deleteCharsLambda(String fromString1, String charsToDelete)
{
BiFunction<String, String, String> deleteChars = (fromString, chars) -> {
StringBuilder buf = new StringBuilder(fromString);
IntStream.range(0, buf.length()).forEach(i -> {
while (i < buf.length() && chars.indexOf(buf.charAt(i)) >= 0)
buf.deleteCharAt(i);
});
return (buf.toString());
};
return deleteChars.apply(fromString1, charsToDelete);
}
static public String deleteCharsReplace(String fromString, String charsToDelete)
{
return fromString.replace(charsToDelete, "");
}
public static void main(String[] args)
{
String str = "XXXTextX XXto modifyX";
String charsToDelete = "X"; // Should only be one char as per OP's requirement
long start, end;
System.out.println("Start simple");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsSimple(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
System.out.println("Start lambda");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsLambda(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
System.out.println("Start replace");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsReplace(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
}
}