更快的替代方案在Java替换字符串的方法?(Faster alternatives to repla

2019-06-23 12:49发布

该替代方法,这一事实返回一个字符串对象,而不是更换定字符串的内容是有点钝(但可以理解的,当你知道字符串是不可变Java中)。 我正在通过使用一些代码嵌套很深的更换打了一个重大的性能。 有什么我可以用它代替将使它更快吗?

Answer 1:

这是StringBuilder的是为。 如果你打算做很多操作的,做它一个StringBuilder ,然后把它转换成一个String ,当您需要。

StringBuilder是这样描述:

“一个可变的字符序列。这类提供的StringBuffer兼容的API,但不保证同步的”。

它已replace (及appendinsertdelete等),你可以使用toString把它演变成一个真正的String



Answer 2:

以前的职位是正确的,StringBuilder的/ StringBuffer的是一个解决方案。

不过,你也不用怀疑,如果它是一个好主意,做在内存大的字符串替换。

我经常被实现为流字符串操作,所以不是字符串中替换它,然后把它发送到一个OutputStream,我做的,把我的字符串发送到OutputStream的时刻更换。 这工作比任何替代快得多。

如果你想这个替换实施模板机制这样更快。 流总是更快,因为你消耗更少的内存,如果客户是缓慢的,你只需要以缓慢的速度产生 - 因此它扩展好得多。



Answer 3:

后续的代码是约。 如果不存在匹配和快5倍,如果有一个匹配快30倍。

static String fastReplace( String str, String target, String replacement ) {
    int targetLength = target.length();
    if( targetLength == 0 ) {
        return str;
    }
    int idx2 = str.indexOf( target );
    if( idx2 < 0 ) {
        return str;
    }
    StringBuilder buffer = new StringBuilder( targetLength > replacement.length() ? str.length() : str.length() * 2 );
    int idx1 = 0;
    do {
        buffer.append( str, idx1, idx2 );
        buffer.append( replacement );
        idx1 = idx2 + targetLength;
        idx2 = str.indexOf( target, idx1 );
    } while( idx2 > 0 );
    buffer.append( str, idx1, str.length() );
    return buffer.toString();
}


Answer 4:

我同意以上所述。 使用StringBuffer的线程安全和StringBuilder的单线程工作时。



Answer 5:

添加到@paxdiablo答案,这里是一个使用StringBuffers比String.replaceAll()快〜3.7倍的replaceAll的样本实现:

码:

public static String replaceAll(final String str, final String searchChars, String replaceChars)
{
  if ("".equals(str) || "".equals(searchChars) || searchChars.equals(replaceChars))
  {
    return str;
  }
  if (replaceChars == null)
  {
    replaceChars = "";
  }
  final int strLength = str.length();
  final int searchCharsLength = searchChars.length();
  StringBuilder buf = new StringBuilder(str);
  boolean modified = false;
  for (int i = 0; i < strLength; i++)
  {
    int start = buf.indexOf(searchChars, i);

    if (start == -1)
    {
      if (i == 0)
      {
        return str;
      }
      return buf.toString();
    }
    buf = buf.replace(start, start + searchCharsLength, replaceChars);
    modified = true;

  }
  if (!modified)
  {
    return str;
  }
  else
  {
    return buf.toString();
  }
}

测试用例 - 输出是下面的(DELTA1 = 1917009502; DELTA2 = 7241000026):

@Test
public void testReplaceAll() 
{
  String origStr = "1234567890-1234567890-";

  String replacement1 =  StringReplacer.replaceAll(origStr, "0", "a");
  String expectedRep1 = "123456789a-123456789a-";

  String replacement2 =  StringReplacer.replaceAll(origStr, "0", "ab");
  String expectedRep2 = "123456789ab-123456789ab-";

  String replacement3 =  StringReplacer.replaceAll(origStr, "0", "");
  String expectedRep3 = "123456789-123456789-";


  String replacement4 =  StringReplacer.replaceAll(origStr, "012", "a");
  String expectedRep4 = "1234567890-1234567890-";

  String replacement5 =  StringReplacer.replaceAll(origStr, "123", "ab");
  String expectedRep5 = "ab4567890-ab4567890-";

  String replacement6 =  StringReplacer.replaceAll(origStr, "123", "abc");
  String expectedRep6 = "abc4567890-abc4567890-";

  String replacement7 =  StringReplacer.replaceAll(origStr, "123", "abcdd");
  String expectedRep7 = "abcdd4567890-abcdd4567890-";

  String replacement8 =  StringReplacer.replaceAll(origStr, "123", "");
  String expectedRep8 = "4567890-4567890-";

  String replacement9 =  StringReplacer.replaceAll(origStr, "123", "");
  String expectedRep9 = "4567890-4567890-";

  assertEquals(replacement1, expectedRep1);
  assertEquals(replacement2, expectedRep2);
  assertEquals(replacement3, expectedRep3);
  assertEquals(replacement4, expectedRep4);
  assertEquals(replacement5, expectedRep5);
  assertEquals(replacement6, expectedRep6);
  assertEquals(replacement7, expectedRep7);
  assertEquals(replacement8, expectedRep8);
  assertEquals(replacement9, expectedRep9);

  long start1 = System.nanoTime();
  for (long i = 0; i < 10000000L; i++)
  {
    String rep =  StringReplacer.replaceAll(origStr, "123", "abcdd");
  }
  long delta1 = System.nanoTime() -start1;

  long start2= System.nanoTime();

  for (long i = 0; i < 10000000L; i++)
  {
    String rep =  origStr.replaceAll( "123", "abcdd");
  }

  long delta2 = System.nanoTime() -start1;

  assertTrue(delta1 < delta2);

  System.out.printf("Delta1 = %d; Delta2 =%d", delta1, delta2);


}


Answer 6:

如果你有多数的绳,以取代(如XML换码序列),尤其是其中所述置换是从图案不同长度的,FSM词法分析器类型算法好像它可能是最有效的,类似的处理的建议以流方式,其中输出逐步建立。

也许一个匹配器对象可以用来做有效。



Answer 7:

刚刚获得char[]中的String ,并遍历它。 使用一个临时StringBuilder

寻找你想要在迭代如果你没有找到模式,写你扫描到的东西来替代模式StringBuilder ,否则写替换文本到StringBuilder



Answer 8:

一般而言,所有的字符串操作是非常慢的。 考虑到用StringBuffer,它不是完全一样的String类,但有很多共同点,这是可变的为好。



Answer 9:

当你更换单个字符,可以考虑遍历你的字符数组,但通过使用(预先创建)替换字符HashMap<Character, Character>()

我使用这个策略,统一标字符为一个整数指数字符串转换。

这是关于快两倍,比String.replace(char, char) 。 需要注意的是关联到创建哈希表的时间不包括在这个比较。



Answer 10:

因为String.replace(CharSequence target, CharSequence replacement)Pattern.compilematcherreplaceAll里面,一个可以稍微通过优化它用于使用预编译目标图案恒定,这样的:

private static final Pattern COMMA_REGEX = Pattern.compile(",");
...
COMMA_REGEX.matcher(value).replaceAll(replacement);


文章来源: Faster alternatives to replace method in a Java String?
标签: java replace