String.replace()不替换所有出现的

时间:2015-10-17 04:20:00

标签: java string replace

我有一个非常长的字符串,看起来与此相似。

355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399,....

当我尝试使用以下代码从字符串中删除数字382时。

String str = "355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399,...."
str = str.replace(",382,", ",");

但似乎并非所有事件都被替换。最初发生3000次以上的字符串在更换后仍留有约630次出现。

String.replace()的功能是否有限?如果是这样,是否有可能实现我的需求?

5 个答案:

答案 0 :(得分:3)

我认为问题是你replace()的第一个参数,特别是382之后之前的逗号(,)。如果你有" 382,​​382,383",你只会匹配内部",382,"并留下最初的一个。尝试:

str.replace("382,", "");

虽然这不符合" 382"在最后,因为它之后没有逗号。

完整的解决方案可能需要两个方法调用:

str = str.replace("382", "");  // Remove all instances of 382
str.replaceAll(",,+", ",");    // Compress all duplicates, triplicates, etc. of commas

这结合了两种方法:

str.replaceAll("382,?", "");  // Remove 382 and an optional comma after it. 

注意:如果382在结尾,则后两种方法都会留下尾随逗号。

答案 1 :(得分:3)

您还需要替换尾随的逗号(如果存在,如果列表中的最后一个则不存在):

str = str.replaceAll("\\b382,?", "");

注意\b字边界以防止匹配"-,1382,-"

以上将转换:

382,111,382,1382,222,382

为:

111,1382,222

答案 2 :(得分:1)

试试这个

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

答案 3 :(得分:1)

首先,删除匹配字符串中的前一个逗号。然后,使用java正则表达式将逗号替换为单个逗号,删除重复的逗号。

 String input = "355,356,357,358,359,360,361,382,363,364,365,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,360,361,363,366,368,369,313,370,371,372,373,374,375,376,377,378,379,380,381,382,382,382,382,382,382,383,384,385,380,381,382,382,382,382,382,386,387,388,389,380,381,382,382,382,382,382,382,390,391,380,381,382,382,382,382,382,392,393,394,395,396,397,398,399";
    String result = input.replace("382,", ","); // remove the preceding comma
    String result2 = result.replaceAll("[,]+", ","); // replace duplicate commas

    System.out.println(result2);

答案 4 :(得分:1)

正如戴夫已经说过的,问题是你的模式重叠了。在字符串"...,382,382,..."中,有两次出现",382,"

"...,382,382,..."
    -----         first occurrence
        -----     second occurrence

这两个匹配项在逗号处重叠,因此Java只能替换其中一个。在查找事件时,它还没有看到您替换模式的内容,因此当替换第一个匹配项时,它不会看到生成",382,"的新事件被替换为逗号。

如果您的数据已知不包含超过3位数的数字,那么您可以这样做:

str.replace("382,", "");

然后作为特例处理最后的事件。但是,如果您的数据可能包含大数字,则"...,1382,..."将替换为"...,1,...",这可能不是您想要的。

以下是两个没有上述问题的解决方案:

首先,只需重复替换,直到不再发生任何变化:

String oldString = str;
str = str.replace(",382,", ",");
while (!str.equals(oldString)) {
    oldString = str;
    str = str.replace(",382,", ",");
}

之后,您将必须处理字符串末尾可能出现的事件。

其次,如果你有Java 8,你可以自己做更多的工作并使用Java流:

str = Arrays.stream(str.split(","))
    .filter(s -> !s.equals("382"))
    .collect(Collectors.joining(","));

首先将字符串拆分为",",然后过滤掉所有等于" 382"的字符串,然后再将其余字符串与"连接, "介于两者之间。

(两个代码段均未经过测试。)