Odpowiedzi:
W java.lang.String
The replace
metoda albo trwa parę char lub parę CharSequence
„s (z których String jest podklasą, więc ona szczęśliwie wziąć parę struny). replace
Metoda zastąpi wszystkie wystąpienia char lub CharSequence
. Z drugiej strony oba String
argumenty do replaceFirst
i replaceAll
są wyrażeniami regularnymi (regex). Korzystanie z niewłaściwej funkcji może prowadzić do subtelnych błędów.
String#replace(target, replacement)
robi to samo, tyle że cytuje ciągi znaków: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
czy istnieje jakiś powód, dla którego String#replace
byłoby szybsze niż String#replaceAll
? Nie wyglądałoby na to, ponieważ String#replace
po prostu wykonuje dodatkowe operacje.
replaceAll
. Odpowiedź brzmi bardziejreplace
P: Jaka jest różnica między java.lang.String
metodami replace()
i replaceAll()
, poza tym, że później używa wyrażenia regularnego.
Odp .: Po prostu regex. Oboje zastępują wszystko :)
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html
PS:
Jest też replaceFirst()
(który wymaga wyrażenia regularnego)
CharSequence
jest. Zarówno replace()
i replaceAll()
„praca z CharSequence
”. Jest tak, że replaceAll()
traktuje podane CharSequence
wyrażenie jako wyrażenie regularne, więc szuka dopasowań wyrażenia regularnego , podczas gdy replace()
uważa podane CharSequence
jako zwykły tekst wyszukiwania, więc szuka jego wystąpienia .
Zarówno replace()
i replaceAll()
zamień wszystkie wystąpienia w ciągu.
Zawsze znajduję przykłady pomocne w zrozumieniu różnic.
replace()
Użyj, replace()
jeśli chcesz po prostu zamienić niektóre na char
inne char
lub niektóre na String
inne String
(faktycznie CharSequence
).
Przykład 1
Zastąpić wszystkie wystąpienia znaku x
z o
.
String myString = "__x___x___x_x____xx_";
char oldChar = 'x';
char newChar = 'o';
String newString = myString.replace(oldChar, newChar);
// __o___o___o_o____oo_
Przykład 2
Zastąpić wszystkie wystąpienia napisu fish
z sheep
.
String myString = "one fish, two fish, three fish";
String target = "fish";
String replacement = "sheep";
String newString = myString.replace(target, replacement);
// one sheep, two sheep, three sheep
replaceAll()
Użyj, replaceAll()
jeśli chcesz użyć wzorca wyrażenia regularnego .
Przykład 3
Zamień dowolny numer na x
.
String myString = "__1_6____3__6_345____0";
String regex = "\\d";
String replacement = "x";
String newString = myString.replaceAll(regex, replacement);
// __x_x____x__x_xxx____x
Przykład 4
Usuń wszystkie białe znaki.
String myString = " Horse Cow\n\n \r Camel \t\t Sheep \n Goat ";
String regex = "\\s";
String replacement = "";
String newString = myString.replaceAll(regex, replacement);
// HorseCowCamelSheepGoat
Dokumentacja
replace(char oldChar, char newChar)
replace(CharSequence target, CharSequence replacement)
replaceAll(String regex, String replacement)
replaceFirst(String regex, String replacement)
Wyrażenia regularne
replace()
Metoda jest przeciążony do zaakceptowania zarówno prymitywne char
i CharSequence
jako argumenty.
Jeśli chodzi o wydajność, replace()
metoda jest nieco szybsza niż replaceAll()
dlatego, że ta ostatnia najpierw kompiluje wzorzec wyrażenia regularnego, a następnie dopasowuje przed ostatecznym zastąpieniem, podczas gdy pierwsza po prostu dopasowuje podany argument i zamienia.
Ponieważ wiemy, że dopasowanie regex wzorzec jest nieco bardziej skomplikowana, a co za tym idzie wolniej, a preferowanie replace()
ponad replaceAll()
sugeruje w miarę możliwości.
Na przykład w przypadku prostych zamian, takich jak wspomniane, lepiej użyć:
replace('.', '\\');
zamiast:
replaceAll("\\.", "\\\\");
Uwaga: powyższe argumenty metody konwersji zależą od systemu.
Pattern.compile(...)
treści / części w swoich implementacjach, wydaje się, że replace
jest mniej skomplikowane w zakresie definiowania / wysyłania pierwszego argumentu. To nie wymaga "\"
. Ponadto replace
jest dostępny od Java 1.5
i replaceAll
od1.4
String replace(char oldChar, char newChar)
Zwraca nowy ciąg wynikający z zamiany wszystkich wystąpień oldChar w tym ciągu na newChar.
String replaceAll(String regex, String replacement
Zastępuje każdy podciąg tego łańcucha, który pasuje do podanego wyrażenia regularnego z podanym zamiennikiem.
Nie jest prawdą, że replace () działa szybciej niż replaceAll (), ponieważ oba wykorzystują ten sam kod w swojej implementacji
Pattern.compile (regex) .matcher (this) .replaceAll (replace);
Teraz pytanie brzmi: kiedy użyć replace i kiedy użyć replaceAll (). Jeśli chcesz zastąpić podciąg innym podciągiem, niezależnie od miejsca jego wystąpienia w ciągu, użyj replace (). Ale jeśli masz jakieś szczególne preferencje lub warunki, takie jak zamień tylko te podciągi na początku lub na końcu łańcucha, użyj replaceAll (). Oto kilka przykładów, które mogą potwierdzić mój punkt widzenia:
String str = new String("==qwerty==").replaceAll("^==", "?"); \\str: "?qwerty=="
String str = new String("==qwerty==").replaceAll("==$", "?"); \\str: "==qwerty?"
String str = new String("===qwerty==").replaceAll("(=)+", "?"); \\str: "?qwerty?"
replace
nie dzwoni Pattern.compile(regex).matcher(this).replaceAll(replacement);
. WzywaPattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
Jak wspomniano w odpowiedzi wickeD, z replaceAll ciąg zastępujący jest traktowany inaczej w zastępstwie i replaceAll. Oczekiwałem, że [3] i [4] będą miały tę samą wartość, ale są różne.
public static void main(String[] args) {
String[] a = new String[5];
a[0] = "\\";
a[1] = "X";
a[2] = a[0] + a[1];
a[3] = a[1].replaceAll("X", a[0] + "X");
a[4] = a[1].replace("X", a[0] + "X");
for (String s : a) {
System.out.println(s + "\t" + s.length());
}
}
Wynikiem tego jest:
\ 1
X 1
\X 2
X 1
\X 2
Różni się to od perla, w którym zamiana nie wymaga dodatkowego poziomu ucieczki:
#!/bin/perl
$esc = "\\";
$s = "X";
$s =~ s/X/${esc}X/;
print "$s " . length($s) . "\n";
który drukuje \ X 2
Może to być dość uciążliwe, jak przy próbie użycia wartości zwracanej przez java.sql.DatabaseMetaData.getSearchStringEscape () z replaceAll ().
Stary wątek Wiem, ale jestem trochę nowy w Javie i odkryłem jedną z dziwnych rzeczy. Użyłem, String.replaceAll()
ale otrzymuję nieprzewidywalne wyniki.
Coś w stylu bałaganu:
sUrl = sUrl.replaceAll( "./", "//").replaceAll( "//", "/");
Więc zaprojektowałem tę funkcję, aby obejść ten dziwny problem:
//String.replaceAll does not work OK, that's why this function is here
public String strReplace( String s1, String s2, String s )
{
if((( s == null ) || (s.length() == 0 )) || (( s1 == null ) || (s1.length() == 0 )))
{ return s; }
while( (s != null) && (s.indexOf( s1 ) >= 0) )
{ s = s.replace( s1, s2 ); }
return s;
}
Które sprawiają, że możesz zrobić:
sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );
String.replaceAll()
oczekuje wyrażeń regularnych, a nie dosłownych argumentów, dlatego otrzymujesz wyniki „nieprzewidywalne” (które są naprawdę bardzo przewidywalne). String.replace()
działa tak, jak chcesz.
Aby dodać do już wybranej „najlepszej odpowiedzi” (i innych, które są tak samo dobre jak Suragch), String.replace()
ogranicza się zastępowanie znaków, które są sekwencyjne (w ten sposób przyjmując CharSequence
). Nie String.replaceAll()
jest jednak ograniczany przez zamianę tylko znaków sekwencyjnych. Można zastąpić znaki niesekwencyjne, o ile wyrażenie regularne jest zbudowane w taki sposób.
Również (co najważniejsze i boleśnie oczywiste) replace()
może jedynie zastąpić wartości dosłowne; podczas gdy replaceAll
może zastąpić sekwencje „podobne” (niekoniecznie identyczne).
replace()
metoda nie używa wzorca wyrażenia regularnego, podczas gdy replaceAll()
metoda używa wzorca wyrażenia regularnego. Więc replace()
działa szybciej niż replaceAll()
.
replace działa na typie danych char, ale replaceAll działa na typie danych String i oba zastępują wszystkie wystąpienia pierwszego argumentu drugim argumentem.
str.replaceAll(regex, repl)
jest takie samo jakPattern.compile(regex).matcher(str).replaceAll(repl)
. Jest więc duży narzut w zależności od tego, ile zużywa się.