replace方法返回字符串对象而不是替换给定字符串的内容这一事实有点让人费解(但是,当您知道字符串在Java中是不变的时,这是可以理解的)。 通过在某些代码中使用深度嵌套的替换,我的性能受到了重大影响。 有什么我可以替换的东西可以使它更快吗?
呵呵替换替换
您使用字符串吗? 你疯了吗? 使用字节数组!
这就是StringBuilder的目的。如果要进行很多操作,请在StringBuilder上进行操作,然后在需要时将其转换为String。
StringBuilder的描述如下:
"A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization".
它具有replace(以及append,insert,delete等),您可以使用toString将其变形为真实的String。
还请记住,如果您不需要线程安全,则通常使用StringBuilder,它通常更快并且工作原理相同。
另外,StringBuilder.replace的工作方式与String.replace完全不同,因此您不能将其用作嵌入式替代品!
前面的帖子是正确的,StringBuilder / StringBuffer是一种解决方案。
但是,您还必须质疑对内存中的大字符串进行替换是否是个好主意。
我经常将String操作实现为流,因此,在将String发送到outputstream的那一刻,我执行了替换操作,而不是将其替换为字符串,然后将其发送到OutputStream。这比任何替换都快得多。
如果您希望此替换实现模板机制,则可以更快地工作。流传输总是更快,因为您消耗的内存更少,并且如果客户端很慢,则只需要以较慢的速度生成文件即可,因此扩展性更好。
你能举个例子吗?
以下代码是大约。如果没有匹配项,则快30倍;如果存在匹配项,则快5倍。
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();
}
您是自己创建还是在某处找到它?我需要像这样的功能来在本机Java中拆分工作吗?任何想法
我不知道了。但它看起来像我的代码样式。我认为我是自己写的。另外,如果设置为副本,我没有设置任何链接或参考。
对不起,我不是那个意思,但要感谢您的回应
我同意以上所述。使用单线程时,请使用StringBuffer来确保线程安全,并使用StringBuilder。
除了@paxdiablo答案,这是使用StringBuffers的replaceAll的示例实现,它比String.replaceAll()快约3.7倍:
码:
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);
}
只需获取String的char[]并对其进行迭代。使用临时StringBuilder。
如果找不到模式,请在迭代时查找要替换的模式,将扫描的内容写入StringBuilder,否则将替换文本写入StringBuilder。
如果要替换的字符串很多(例如XML转义序列),尤其是替换的长度与模式长度不同时,FSM lexer类型算法似乎是最有效的,类似于以流方式进行处理的建议,其中将逐步构建输出。
也许可以使用Matcher对象来有效地做到这一点。
由于String.replace(CharSequence target, CharSequence replacement)内部具有Pattern.compile,matcher,replaceAll,因此可以使用预编译的目标模式常量对其进行稍微优化,如下所示:
private static final Pattern COMMA_REGEX = Pattern.compile(",");
...
COMMA_REGEX.matcher(value).replaceAll(replacement);
当您替换单个字符时,请考虑遍历您的字符数组,但要使用(预先创建的)HashMap()替换字符。
我使用此策略通过Unicode上标字符转换整数指数字符串。
它是String.replace(char, char)的两倍。请注意,与创建哈希映射表相关的时间不包括在此比较中。
通常,所有字符串操作都非常慢。考虑使用StringBuffer,它与String类并不完全一样,但是有很多共同点,并且也是可变的。
通常,如果您不需要缓冲区是线程安全的(即您没有多个线程一次操作同一缓冲区),则应使用StringBuilder而不是StringBuffer。
从StringBuffer文档中:StringBuilder类通常优先于此类使用,因为它支持所有相同的操作,但是它更快,因为它不执行同步。
我过去经常在多线程环境中工作,所以StringBuffer自然而然地出现在我的脑海中。
不知道为什么这个问题引起了骚动。