String replace () ve replaceAll () arasındaki fark


221

Java.lang.String replace()ve replaceAll()yöntemleri arasındaki fark nedir , daha sonra regex kullanır? Yerine severim basit değiştirmelerin için .birlikte / , herhangi bir fark var mı?

Yanıtlar:


174

İçinde java.lang.String, replaceyöntem ya bir çift karakter veya bir çift CharSequence's alır (bunlardan biri String bir alt sınıftır, bu yüzden mutlu bir şekilde bir String dizisi alır). replaceYöntem, bir char veya tüm tekrarlarını yerini alacak CharSequence. Öte yandan, her iki Stringbağımsız değişkenleri replaceFirstve replaceAlldüzenli ifadeler (regex) bulunmaktadır. Yanlış fonksiyonun kullanılması ince hatalara yol açabilir.


30
Ayrıca, java belgelerine göre, her çağrı str.replaceAll(regex, repl)aynıdır Pattern.compile(regex).matcher(str).replaceAll(repl). Yani ne kadar kullanıldığına bağlı olarak büyük bir ek yük var.
user845279

4
@ user845279 String#replace(target, replacement)Aynı şeyi yaptığından beri , dizeleri alıntılamak dışında şunu söylemek ilginçtir : Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));Neden String#replacedaha hızlı olmasının bir nedeni var mı String#replaceAll? Sadece String#replaceek işlemler gerçekleştirdiği için öyle görünmüyor .
Horsey

1
Sadece merak ediyorum, bu cevapta açık karşılaştırma nerede replaceAll. Cevap daha fazlareplace
Manuel Jordan

Bu, replaceAll () ifadesinin normal ifade eşleşmesi nedeniyle daha pahalı olacağı anlamına mı geliyor?
merak

98

S: arasındaki fark nedir java.lang.Stringyöntemlerle replace()ve replaceAll()daha sonraki kullanımları regex bunun dışında.

C: Sadece normal ifade. İkisi de hepsinin yerini alıyor :)

http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

Not:

Ayrıca bir replaceFirst()(normal ifadeyi alan)


1
Sadece normal ifade olduğunu açıklamak için teşekkürler. Nasıl isterdim onlar adlandırmak yerine replaceWithRegex () yerine replaceAll ()
HopeKing

Açıklama: replaceAll () normal ifadelerle çalışır, replace () CharSequence ile çalışır
Johnny Five

2
@JohnnyFive Bu daha kafa karıştırıcı. Düzenli ifade bir tür değildir CharSequence. Her ikisi de replace()ve replaceAll()"ile çalışmak CharSequence". Bu işte replaceAll()verilen gördüğü CharSequenceo arar böylece normal ifade olarak Normal ifade eşleşirse ederken, replace()verilen gördüğü CharSequenceo arar böylece düz arama metin olarak geçtiği o.
SantiBailors

44

Hem replace()ve replaceAll()dize tüm tekrarlarını değiştirmek.

Örnekler

Farklılıkları anlamak için örnekleri daima yararlı buluyorum.

replace()

Kullan replace()sadece biraz değiştirmek istiyorsanız charbirbirleriyle charya da bazı Stringbaşka ile String(aslında CharSequence).

örnek 1

Karakteri tüm tekrarlarını değiştirmek xile 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_

ÖRNEK 2

Dize tüm oluşumları değiştirin fishile 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()

Kullanım replaceAll()Bir kullanmak istiyorsanız normal ifade desenini .

ÖRNEK 3

Herhangi bir sayıyı bir ile değiştirin 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

Örnek 4

Tüm boşlukları kaldırın.

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

Ayrıca bakınız

belgeleme

Düzenli ifadeler


34

replace()Yöntem, ilkel hem kabul aşırı charbir CharSequencebağımsız değişken olarak.

Performans söz konusu olduğunda, replace()yöntem biraz daha hızlıdır, replaceAll()çünkü ikincisi ilk önce normal ifade desenini derler ve daha sonra nihayet değiştirilmeden önce eşleşir, oysa eski basitçe sağlanan argümanla eşleşir ve değiştirir.

O zaman tercih regex desen eşleştirme dolayısıyla daha yavaş biraz daha karmaşık ve olduğunu bildiğimiz için replace()üzerinde replaceAll()mümkün olduğunca ileri sürülmektedir.

Örneğin, bahsettiğiniz gibi basit ikameler için kullanmak daha iyidir:

replace('.', '\\');

onun yerine:

replaceAll("\\.", "\\\\");

Not: Yukarıdaki dönüşüm yöntemi bağımsız değişkenleri sisteme bağlıdır.


6
Değiştirmek de aynısını yapar, Java String docs :: public String replace (CharSequence target, CharSequence replacement) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (replacement.toString ())); }
Prateek

@Prateek: jdk8'den sonra, String :: replace artık Desen kullanmıyor: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , jdk11'de aynı.
Franck

Kabul et, Java 8'de pratik olarak her iki yöntem de hemen hemen aynıdır, çünkü her ikisi de Pattern.compile(...)uygulamalarındaki içerik / bölüm görünür replace, ilk argümanın nasıl tanımlanacağı / gönderileceği konusunda daha az karmaşık görünüyor . Gerektirmez "\". Ayrıca replaceJava beri 1.5ve replaceAllberi kullanılabilir1.4
Manuel Jordan

3
String replace(char oldChar, char newChar)

Bu dizedeki tüm oldChar örneklerini newChar ile değiştirerek oluşan yeni bir dize döndürür.

String replaceAll(String regex, String replacement

Bu dizenin verilen normal ifadeyle eşleşen her bir alt dizesini verilen değiştirmeyle değiştirir.


3
  1. Replace () ve replaceAll () iki bağımsız değişkeni kabul eder ve bir dizgideki ilk alt dizenin (ilk bağımsız değişken) tüm örneklerini ikinci alt dizeyle (ikinci bağımsız değişken) değiştirir.
  2. replace () bir çift karakter veya charsequence kabul eder ve replaceAll () bir çift normal ifade kabul eder.
  3. Replace () öğesinin replaceAll () yönteminden daha hızlı çalıştığı doğru değildir, çünkü her ikisi de uygulamasında aynı kodu kullanır

    Pattern.compile (normal ifade) .matcher (bu) .ReplaceAll (değiştirme);

Şimdi soru, replace ne zaman kullanılacağı ve replaceAll () ne zaman kullanılacağıdır. Bir alt dizeyi dizede meydana geldiği yerden bağımsız olarak başka bir alt dize ile değiştirmek istediğinizde replace () kullanın. Ancak, yalnızca bir dizenin başında veya sonunda bulunan alt dizeleri değiştirmek gibi belirli bir tercih veya koşulunuz varsa replaceAll () öğesini kullanın. Demek istediğimi kanıtlamak için bazı örnekler:

String str = new String("==qwerty==").replaceAll("^==", "?"); \\str: "?qwerty=="
String str = new String("==qwerty==").replaceAll("==$", "?"); \\str: "==qwerty?"
String str = new String("===qwerty==").replaceAll("(=)+", "?"); \\str: "?qwerty?"

4
Aynı uygulama değildirler. replaceçağırmaz Pattern.compile(regex).matcher(this).replaceAll(replacement);. Bu çağrılarPattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils

replaceAll () bir çift regex'i kabul eder Neden hem arama dizesi hem de değiştirme dizesi normal ifade olur? Olayların yerini ne alacaktı? Normal ifade ile mi? Tabii ki sadece ilk argüman bir normal ifade (arama dizesi). İkincisi bir normal ifade değildir (yeni dize).
SantiBailors

1

Kötü cevabın cevabında belirtildiği gibi, replaceAll ile değiştirme dizesi, replace ve replaceAll arasında farklı işlenir. [3] ve [4] 'ün aynı değere sahip olmasını bekledim, ancak bunlar farklı.

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

Bunun çıktısı:

\   1
X   1
\X  2
X   1
\X  2

Bu, değiştirme işleminin fazladan kaçma gerektirmediği perl'den farklıdır:

#!/bin/perl
$esc = "\\";
$s = "X";

$s =~ s/X/${esc}X/;
print "$s " . length($s) . "\n";

yazdırılan \ X 2

ReplaceAll () ile java.sql.DatabaseMetaData.getSearchStringEscape () tarafından döndürülen değeri kullanmaya çalışırken, bu oldukça sıkıntı verici olabilir.


0

Eski iş parçacığı biliyorum ama Java için biraz yeni ve garip şeylerden birini keşfetmek. Kullandım String.replaceAll()ama öngörülemeyen sonuçlar elde ettim .

Böyle bir şey dizeyi berbat:

sUrl = sUrl.replaceAll( "./", "//").replaceAll( "//", "/");

Bu fonksiyonu garip problemi çözmek için tasarladım:

//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;
}

Yapabilmenizi sağlayan:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );

1
String.replaceAll()değişmez argümanlar değil normal ifadeler bekler , bu yüzden "tahmin edilemez" (gerçekten çok tahmin edilebilir) sonuçlar elde edersiniz. String.replace()istediğiniz gibi çalışır.
Nadar

Java'dan beklenmedik sonuçlar elde ettiğimizde önemli bir kural olarak, bunun üstesinden gelmek için yeni bir işlev tasarlamak yerine, bu sonuçların doğru olduğunu ve kullandığımız Java işlevini yanlış anladığımızı varsaymak daha iyidir.
SantiBailors

0

Zaten seçili olan "En İyi Cevap" a (ve Suragch'ınki kadar iyi olanlara) eklemek String.replace(), sıralı karakterlerin (böylece alarak CharSequence) değiştirilmesiyle sınırlıdır . Ancak, String.replaceAll()yalnızca sıralı karakterlerin değiştirilmesi ile kısıtlanmaz. Normal ifadeniz bu şekilde oluşturulduğu sürece sıralı olmayan karakterleri de değiştirebilirsiniz.

Ayrıca (en önemlisi ve acıyla bariz), replace()sadece değişmez değerlerin yerini alabilir; oysa replaceAll'benzer' sekansların yerini alabilir (mutlaka aynı değildir).


-1

replace()yöntem normal ifade kalıbı replaceAll()kullanmazken yöntem normal ifade kalıbı kullanır. Böylece replace()daha hızlı çalışır replaceAll().


3
bu doğru değil. Eğer değiştirme kaynağına bakarsanız, bunun aynı zamanda Desen ve
Eşleştirici

-5

replace, char veri türünde çalışır ancak replaceAll, String veri türü üzerinde çalışır ve her ikisi de, ilk bağımsız değişkenin tüm örneklerini ikinci bağımsız değişkenle değiştirir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.