まず、問題のデモ:
String s = "I have three cats and two dogs.";
s = s.replace("cats", "dogs")
.replace("dogs", "budgies");
System.out.println(s);
これは、cats => dogsおよびdogs => budgiesを置き換えることを目的としていますが、順次置換は以前のr不都合な出力は次のとおりです。
私には3つのbudgiesと2つのbudgiesがあります。
これは私の同時置換方法の実装です。それはString.regionMatches
を使用して書くことは簡単です:
public static String simultaneousReplace(String subject, String... pairs) {
if (pairs.length % 2 != 0) throw new IllegalArgumentException(
"Strings to find and replace are not paired.");
StringBuilder sb = new StringBuilder();
int numPairs = pairs.length/2;
outer:
for (int i = 0; i < subject.length(); i++) {
for (int j = 0; j < numPairs; j++) {
String find = pairs[j * 2];
if (subject.regionMatches(i, find, 0, find.length())) {
sb.append(pairs[j * 2 + 1]);
i += find.length() - 1;
continue outer;
}
}
sb.append(subject.charAt(i));
}
return sb.toString();
}
テスト:
String s = "I have three cats and two dogs.";
s = simultaneousReplace(s,
"cats", "dogs",
"dogs", "budgies");
System.out.println(s);
出力:
私は3匹の犬と2匹のセキセイインコを持っています。
さらに、最も長いマッチを探すために、同時に交換するときに便利なことがあります。 (例えば、PHPのstrtr
関数はこれを行います。)これは私の実装です:
public static String simultaneousReplaceLongest(String subject, String... pairs) {
if (pairs.length % 2 != 0) throw new IllegalArgumentException(
"Strings to find and replace are not paired.");
StringBuilder sb = new StringBuilder();
int numPairs = pairs.length/2;
for (int i = 0; i < subject.length(); i++) {
int longestMatchIndex = -1;
int longestMatchLength = -1;
for (int j = 0; j < numPairs; j++) {
String find = pairs[j * 2];
if (subject.regionMatches(i, find, 0, find.length())) {
if (find.length() > longestMatchLength) {
longestMatchIndex = j;
longestMatchLength = find.length();
}
}
}
if (longestMatchIndex >= 0) {
sb.append(pairs[longestMatchIndex * 2 + 1]);
i += longestMatchLength - 1;
} else {
sb.append(subject.charAt(i));
}
}
return sb.toString();
}
なぜこれが必要ですか?例は次のとおりです。
String truth = "Java is to JavaScript";
truth += " as " + simultaneousReplaceLongest(truth,
"Java", "Ham",
"JavaScript", "Hamster");
System.out.println(truth);
出力:
をハムたちはsimultaneousReplace
代わりのsimultaneousReplaceLongest
を使用していた場合、出力は "HamScript" を持っているだろうハムスター
にそのままJavaはJavaScriptにあります「ハムスター」の代わりに:
上記の方法では大文字と小文字が区別されます。大文字小文字を区別しないバージョンが必要な場合は、String.regionMatches
がignoreCase
パラメータを取ることができるため、上記を変更するのは簡単です。
関連スレッド - http://stackoverflow.com/questions/2049528/java-best-way-for-string-find-and-replace – adatapost