356 Stimmen

Alle Vorkommen von char aus String entfernen

Ich kann das verwenden:

String str = "TextX Xto modifyX";
str = str.replace('X','');//that does not work because there is no such character ''

Gibt es eine Möglichkeit, alle Vorkommen von Zeichen zu entfernen X aus einer Zeichenkette in Java?

Ich habe das versucht und es ist nicht das, was ich will: str.replace('X',' '); //replace with space

3voto

Volksman Punkte 1901

Bewertung der Hauptantworten mit einem Leistungsbenchmark, der die Befürchtung bestätigt, dass die aktuell gewählte Antwort unter der Haube kostspielige Regex-Operationen durchführt

Bislang gibt es 3 Arten von Antworten (ohne die JavaScript-Antwort ;) ):

  • Verwenden Sie String.replace(charsToDelete, ""); das verwendet Regex unter der Haube
  • Lambda verwenden
  • Einfache Java-Implementierung verwenden

In Bezug auf die Codegröße ist String.replace eindeutig am knappsten. Die einfache Java-Implementierung ist etwas kleiner und sauberer (IMHO) als das Lambda (verstehen Sie mich nicht falsch - ich verwende Lambdas oft, wo sie angemessen sind)

Die Ausführungsgeschwindigkeit war, in der Reihenfolge vom schnellsten zum langsamsten: einfache Java-Implementierung, Lambda und dann String.replace() (das Regex aufruft).

Die bei weitem schnellste Implementierung war die einfache Java-Implementierung, die so eingestellt wurde, dass sie den StringBuilder-Puffer auf die maximal mögliche Ergebnislänge vorallokiert und dann einfach Zeichen an den Puffer anhängt, die nicht in der Zeichenkette "zu löschende Zeichen" enthalten sind. Dadurch werden Neuzuweisungen vermieden, die bei Strings mit einer Länge von mehr als 16 Zeichen auftreten würden (die Standardzuweisung für StringBuilder), und es wird der Leistungseinbruch beim Löschen von Zeichen aus einer Kopie des Strings vermieden, der bei der Lambda-Implementierung auftritt.

Der folgende Code führt einen einfachen Benchmark-Test durch, bei dem jede Implementierung 1.000.000 Mal ausgeführt wird und die verstrichene Zeit protokolliert wird.

Die genauen Ergebnisse variieren bei jedem Durchlauf, aber die Reihenfolge der Leistungen ä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) kann langsamer sein, weil sie eine "Verschiebung nach links um eins" aller Zeichen rechts von dem zu löschenden Zeichen durchführt. Dies würde sich natürlich bei längeren Zeichenfolgen mit vielen zu löschenden Zeichen verschlechtern. Außerdem könnte es in der Lambda-Implementierung selbst einen gewissen Overhead geben.

Die String.replace-Implementierung verwendet Regex und führt bei jedem Aufruf ein Regex-"Compile" durch. Eine Optimierung wäre die direkte Verwendung von regex und die Zwischenspeicherung des kompilierten Musters, um die Kosten für die Kompilierung bei jedem Aufruf 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));
    }
}

3voto

Arefe Punkte 8879

Sie müssen die zu entfernenden Zeichen während der Ersetzung in die eckigen Klammern setzen. Der Beispielcode sieht wie folgt aus:

String s = "$116.42".replaceAll("[$]", "");

2voto

Gerrit B Punkte 184

Ich verwende bei dieser Gelegenheit gerne RegEx:

str = str.replace(/X/g, '');

wobei g für global steht, so dass die gesamte Zeichenkette durchlaufen wird und alle X durch '' ersetzt werden; wenn Sie sowohl X als auch x ersetzen wollen, sagen Sie einfach:

str = str.replace(/X|x/g, '');

(siehe meine Fiedel hier: fiddle )

2voto

Ayushi Jain Punkte 680

Verwenden Sie replaceAll anstelle von replace

str = str.replaceAll("X,"");

Damit sollten Sie die gewünschte Antwort erhalten.

0voto

Kaplan Punkte 1226

hier ist eine Lambda-Funktion, die alle als String übergebenen Zeichen entfernt

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() );
};

String str = "TextX XYto modifyZ";
deleteChars.apply( str, "XYZ" ); // –> "Text to modify"

Bei dieser Lösung wird berücksichtigt, dass der resultierende String - im Gegensatz zu replace() - wird beim Entfernen von Zeichen nie größer als die Anfangszeichenfolge. So wird das wiederholte Zuweisen und Kopieren beim zeichenweisen Anhängen an den StringBuilder como replace() tut.
Ganz zu schweigen von der sinnlosen Erzeugung von Pattern y Matcher Instanzen in replace() die nie zum Entfernen benötigt werden.
Im Unterschied zu replace() Mit dieser Lösung können mehrere Zeichen auf einen Schlag gelöscht werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X