【问题标题】:Replace with empty string replaces newChar around all the characters in original string替换为空字符串替换原始字符串中所有字符周围的 newChar
【发布时间】:2016-03-01 19:57:44
【问题描述】:

我只是在处理我使用 Java String.replace 方法的 java 代码之一。因此,在一种情况下测试替换方法时,我计划将垃圾值设为String.replace("","");

在测试中,我遇到了用其他值替换空白值的条件,即 String.replace("","p") 替换了原始字符串所有字符周围的 "p"

例子:

String strSample = "val";
strSample = strSample.replace("","p");
System.out.println(strSample);

输出:

pvpaplp

谁能解释一下为什么会这样?

【问题讨论】:

  • 哪一部分让您感到困扰——它取代了“中间”这一事实?还是它取代了不止一个?
  • 这是因为replace 使用了正则表达式,并且正则表达式"" 在4 个位置匹配val:每个字母之前和最后一个字母之后。
  • replace 不使用正则表达式,replaceAll 使用。
  • @ForguesR 确实如此,replace(CharSequence, CharSequence) 在内部使用 replaceAll
  • @ForguesR replace 不使用正则表达式 syntax,但它使用正则表达式 engine。它只是自动为所有正则表达式元字符添加转义机制。

标签: java string replace


【解决方案1】:

replace 查找您拥有以替换字符串开头的字符串的每个地方。例如如果你在“banana”中替换“a”,它会找到“a”3次。

但是,对于空字符串,它会在任何地方找到它,包括最后一个字母之前和之后。

【讨论】:

    【解决方案2】:

    以下是 Java 文档中对您案例的重载 replace 方法的定义。

    String java.lang.String.replace(CharSequence 目标, CharSequence 替换

    替换此字符串中与文字目标匹配的每个子字符串 具有指定文字替换序列的序列。这 替换从字符串的开头到结尾进行,对于 例如,将字符串“aaa”中的“aa”替换为“b”将导致 “ba”而不是“ab”。

    参数:
    target要替换的char值的顺序
    replacement char值的替换顺序

    现在,由于您将 target 值定义为 "" 即为空,因此它将选择字符串中的每个位置并将其替换为 replacement 中定义的值。

    需要注意的一点是,如果您将使用strSample = strSample.replace(" ","p");,这意味着一个空白字符作为target 值,则不会替换任何内容,因为现在在这种情况下replace 方法将尝试搜索一个白色空格字符。

    【讨论】:

    • @Mr. downvoter:有什么理由拒绝投票??投反对票和参选是一种很糟糕的精神表现,但却没有勇气支持你的理由。
    • @ForguesR 伙计,我希望你有充分的理由,并且你已经理解“否决票”的含义。否决票不是您在回答问题时使用的按钮,并且出于喘息之需,您希望其他答案的票数比您少。否决票意味着答案没有用且无关紧要。现在我使用了 Java 文档中的信息并对其进行了解释,所以它不会出错。此外,您也或多或少地提供了与冗余垃圾相同的信息。
    • @ForguesR 我不期待你的投票逆转,更多的是关于你的非理性行为和反对投票的理由。
    【解决方案3】:

    本机 Java java.lang.String 实现(如 Ruby 和 Python)在执行字符串操作时将空字符串 "" 视为有效字符序列。因此"" 字符序列实际上是everywhere 介于两个字符之间,包括最后一个字符之前和之后。

    它与所有java.lang.String 操作一致。见:

    String abc = "abc";
    System.out.println(abc.replace("", "a"));  // aaabaca instead of "abc"
    System.out.println(abc.indexOf("", "a"));  // 0 instead of -1
    System.out.println(abc.contains("", "a")); // true instead of false
    

    附注:

    这种行为可能会产生误导,因为许多其他语言/实现的行为并非如此。例如,SQL(MySQL、MSSQL、Oracle 和 PostgreSQL)和 PHP 不会将 "" 视为字符串替换的有效字符序列。 .NET 更进一步,在调用 abc.Replace("", "a") 时会抛出 System.ArgumentException: String cannot be of zero length.

    即使是流行的 Apache Commons Lang Java 库也有不同的工作方式:

    org.apache.commons.lang3.StringUtils.replace("abc", "", "a")); /* abc */
    

    【讨论】:

    • 您不是直接回答 OP 的问题,而是用大量冗余和不相关的信息夸大您的答案。您正在引用 org.apache.commons.lang3.StringUtils.replace 但它是一个库而不是一种语言,您可以创建一个库来做任何您想做的事情,现在这并不意味着该语言支持或不支持它。 Op 不想知道世界上其他 1000 种语言中发生了什么,但想了解 Java 中的行为。
    • @hagrawal 感谢您的评论,我编辑了我的答案。 OP 想了解java.lang.String 的行为。我还要补充一点,org.apache.commons.lang 不是自制的 String 库,而是一个非常流行的 Java 库,其替换功能与原生 java.lang.String 的工作方式不同。
    【解决方案4】:

    看看这个例子:

    "" + "abc" + ""
    

    这段代码的结果是什么?
    答:还是"abc"。如您所见,我们可以说所有字符串前后都有一些空字符串。

    同样的规则适用于中间字符,如

    "a"+""+"b"+""+"c"
    

    仍将创建"abc"

    所以字符之间也存在空字符串。

    在您的代码中

    "val".replace("","p")
    

    所有这些空字符串都被替换为p,从而导致pvpaplp


    ""+""+..+""+"" 的情况下,假设Java 足够聪明,可以将其视为""

    【讨论】:

    • 那么你可以争辩说"a"+""+"b" == "a"+""+""+""+""+"b" 那么为什么p 不会被替换4次呢? (狡猾的推理他?)
    • @Tunaki 该死的。我试图避免这个问题,因为呈现的逻辑允许更容易记住一般想法,而不是涵盖所有细节:)
    • 是的,我明白你的意思了:)
    猜你喜欢
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    相关资源
    最近更新 更多