0

Java 有 replace() 和 replaceAll() 方法可以用给定的新模式替换字符串的部分/序列。该函数的内部是如何工作的?如果我必须编写一个函数来输入字符串、OldPattern、NewPattern 并在不使用 RegEx的情况下递归地用NewPattern 替换每次出现的 OldPattern怎么办?我已经使用 String 输入的迭代完成了以下代码,它似乎可以工作。如果输入是字符数组而不是字符串怎么办?

  public String replaceOld(String aInput, String aOldPattern, String aNewPattern)
        {
             if ( aOldPattern.equals("") ) {
                throw new IllegalArgumentException("Old pattern must have content.");
             }

             final StringBuffer result = new StringBuffer();
             int startIdx = 0;
             int idxOld = 0;
             while ((idxOld = aInput.indexOf(aOldPattern, startIdx)) >= 0) {
               result.append( aInput.substring(startIdx, idxOld) );
               result.append( aNewPattern );

               //reset the startIdx to just after the current match, to see
               //if there are any further matches
               startIdx = idxOld + aOldPattern.length();
             }
             //the final chunk will go to the end of aInput
             result.append( aInput.substring(startIdx) );
             return result.toString();
          }
4

3 回答 3

4

Java 有 replace() 和 replaceAll() 方法可以用给定的新模式替换字符串的部分/序列。

准确地说,这些方法创建了替换相关字符的新字符串。Java 字符串是不可变的。

该函数的内部是如何工作的?

这太复杂了,无法在这里详细解释。(并且细节实际上可能因一种实现而异)。最好的办法是自己阅读相关库类的源代码。(源代码作为 JDK 的一部分分发,您的 Java IDE 应该能够向您展示它。或者,谷歌搜索会在网络上为您找到它。)

如果我必须编写一个函数来输入字符串、OldPattern、NewPattern 并在不使用 RegEx 的情况下递归地用 NewPattern 替换每次出现的 OldPattern 怎么办?

好吧,如果您正在谈论在不使用Pattern该类的情况下进行模式匹配/替换,那么是的,这很棘手……更不用说毫无意义了。

(递归解决方案可能很危险。考虑这个问题:“递归地用“a”中的“ba”替换“a”的所有实例。结果应该是什么?你甚至应该尝试这样做吗?)


假设参数是简单的字符串(不是您描述的模式),那么这里是一个递归解决方案(未经测试):

public String replace1(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    String updated = in.substring(0, pos) + replacement + 
                     in.substring(pos + target.length());
    return replace1(updated, target, replacement);
}

这解决了1您希望替换为递归的问题版本;即您要替换target由替换过程插入的实例的位置。如果您不想这样做,那么:

public String replace2(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    return in.substring(0, pos) + replacement + 
                     replace2(in.substring(pos + target.length()),
                             target, replacement);
}

请注意,这些很可能您最初的迭代解决方案效率低。甚至忽略正在进行的所有字符串复制。Java 不进行尾调用优化。


1 - 如果你replace1用病态参数调用,你会得到堆栈溢出。例如replace1("ab", "b", "b")

于 2013-01-22T03:26:45.953 回答
1

尝试

public static String replaceOld(String aInput, String aOldPattern, String aNewPattern, int i) {
    i = aInput.indexOf(aOldPattern, i);
    if (i == -1) {
        return aInput;
    }
    aInput = aInput.substring(0, i) + aNewPattern + aInput.substring(i + aOldPattern.length());
    return replaceOld(aInput, aOldPattern, aNewPattern, i + aNewPattern.length());
}

请注意,parami用于优化,因此 indexOf 不会每次都从 pos 0 开始扫描。它还解决了“a”问题中“递归地用“ba”替换“a”的所有实例。

于 2013-01-22T05:27:21.100 回答
0

也许这种方法会回答你的问题。

  static int indexOf(char[] string, char[] pattern, int startIndex) {
     int index = startIndex;
     while(true) {
         while(index < string.length && string[index] != pattern[0]) index++;
         if(index >= string.length || index+pattern.length > string.length) return -1;
         boolean match = true;
         for(int i = 1; i < pattern.length; i++) {
             if(string[index+i] != pattern[i]) {
                 match = false;
                 break;
             }
         }
         if(match) return index;
         else index += 1;
     }
  }

如果你想要一个递归替换方法,使用这个

static String replace(String string, String pattern, String replacement) {
  int index = string.indexOf(pattern);
  if(index < 0) return string;
  int endIndex = index+pattern.length();
  return string.substring(0, index) + replacement +
      replace(string.substring(endIndex), pattern, replacement);
}
于 2013-01-22T03:36:04.600 回答