【问题标题】:Java replace all replacing one of every two occurrencesJava替换所有替换每两次出现之一
【发布时间】:2018-06-28 03:05:02
【问题描述】:

在一个非常简单的问题上,我有一个奇怪的行为。

我有一个包含很多空字符串的字符串:

“a;b;c;null;null;null;null;null;null;null;null;null;null”

我使用此方法删除:

public String replaceAllNull(String s) {
    s = s.replaceAll(";null;", ";;");

    //if first item = null remove it
    if(s.startsWith("null;")) {
        s = s.substring(4,s.length());
    }

    //if last item = null remove it
    if(s.endsWith(";null")) {
        s = s.substring(0,s.length()-4);
    }
    return s;
}

它工作正常,直到我的字符串变大,我看到这个奇怪的输出

“a;b;c;;null;;null;;null;;null;;”

它只删除了两次出现中的一次。

我想我可以理解,在一个替换程序中会跳过一个“;”然后我的正则表达式“;null;”无法识别第二个null。但我不明白为什么会这样?

【问题讨论】:

  • 拆分';',删除"null"字符串,重新加入';'

标签: java string replaceall


【解决方案1】:

";null;" 的一个实例被";;" 替换后,两个分号都已被处理,因此第二个; 不能被视为下一个";null;" 出现的另一个替换的开始。在传递另一个“null”到达下一个分号之前,无法再次匹配该模式。

您可以使用不尝试匹配分号的模式,但它必须检查它们是否存在。您可以使用a positive lookbehind and a positive lookahead(在链接页面上找到“lookahead”和“lookbehind”)。在这里,肯定的意思是它验证了lookbehind/lookahead的模式存在,但不匹配。

正向回溯格式为(?<=X),其中X 是在主模式后面查看是否存在的模式。此外,正向前瞻的格式为(?=X),其中X 是先于主模式查看是否存在的模式。

在这里,我们在匹配前查找^ 行的开头或分号,以及匹配后$ 或分号的行尾。然后我们只需将实际匹配项"null" 替换为一个空字符串。

s = s.replaceAll("(?<=^|;)null(?=$|;)", "");

【讨论】:

  • 这行得通,我在junits测试中对其进行了测试,它满足了所有的测试用例,谢谢!
【解决方案2】:

您可以通过拆分字符串来使用流

return Stream.of(s.split(";", -1))
             .map(w -> "null".equals(w) ? "" : w)
             .collect(Collectors.joining(";"));

【讨论】:

  • ';'包围的空字符串不会有同样的问题吗?过滤器不是比地图更合适吗?
  • @FedericoklezCulloca 过滤器删除了元素,因此 ;会更少。不知道你说的第一个问题是什么意思。这将删除用空字符串替换每个 null 单元格。
  • 我的意思是情况将保留为“a;b;c;;;;;;;;;;”因为map 返回的内容内部将有空字符串,我不确定这是 OP 想要的:这可能只是我的印象,但我认为所需的结果是“a;b;c”。这就是我建议使用过滤器的原因。
  • 想要的结果是“a;b;c;;;;;;;;;;” (在我的情况下是需要的)我用不同的情况测试了这个答案,它正在工作!
  • @RedRaccoon 您可以通过单击左侧的勾号来接受答案。
【解决方案3】:

一个很简单的解决方案,用这个代替上面的大代码

public String replaceAllNull(String s) {
    return s.replace("null" , "");
}

例子

 public static void main(String []args){
    String str = "a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;";
    System.out.println(String.format("Before replacing null %s", str));
    str = replaceAllNull(str);
    System.out.println(String.format("After replacing null %s", str));
}

输出

Before replacing null a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;
After replacing null a;r;c;e;;d;f;e;;s;;;;;;;;;;;;;;;;;s;

更新,避免出现这种包含 null 的词,这里是替代词

public static String replaceAllNull(String s) {
    String[] arr = s.split(";");
    for (int i = 0; i < arr.length; i++) {
        if (arr[i].equalsIgnoreCase("null"))
            arr[i] = "";
    }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < arr.length; i++) {
        sb.append(arr[i]);
        if (i < arr.length - 1)
            sb.append(";");
    }
    if (s.endsWith(";"))
        sb.append(";");
    return sb.toString();
}

【讨论】:

  • 这也会改变一个包含 null 的单元格,但这可能是一个合理的假设。例如取消无效的无效无效无效无效无效无效无效无效无效无效无效无效无效无效无效无效无效
猜你喜欢
  • 1970-01-01
  • 2021-12-20
  • 2011-08-17
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 2018-09-08
相关资源
最近更新 更多