字符串替换速度测试
现有三种处理方法
①网络上搜寻的工具类
/**
* @param src 替换的文本源
* @param target 目标的词汇
* @param replacement 替换后的词汇
* @return java.lang.String
* @Author yujiankai
* @Description 数组替换
* @date 2021/12/7 16:25
*/
public static String replaceAllStr(String src, String target, String replacement) {
if (src == null || target == null || replacement == null) return src;
int idx = src.indexOf(target);
//不存在则返回
if (idx == -1) return src;
int pst = 0;
char[] cs = src.toCharArray();
//替换后的新数组初始化
char[] rs = new char[src.length() - target.length() + replacement.length()];
for (int i = 0; i < cs.length; i ++) {
if (i == idx) {
//替换阶段
for (char c : replacement.toCharArray()) {
rs[pst] = c;
pst ++;
}
continue;
}
if (i > idx && i < idx + target.length()) continue;
//替换之前的数组赋值
rs[pst] = cs[i];
pst ++;
}
return replaceAllStr(new String(rs), target, replacement);
}
②自己写的工具类
public static String replaceAllStr2(String src, String target, String replacement){
return replaceAllStr2(src,target,replacement,new String());
}
/**
* @param src
* @param target
* @param replacement
* @return java.lang.String
* @Author yujiankai
* @Description 字符串拼接替换
* @date 2021/12/7 16:30
*/
private static String replaceAllStr2(String src, String target, String replacement,String result) {
if (src == null || target == null || replacement == null) return src;
int idx = src.indexOf(target);
if (idx == -1) return result+src;
result += src.substring(0,idx)+replacement;
src = src.substring(idx + target.length());
return replaceAllStr2(src, target, replacement, result);
}
③StringUtils工具类
/**
* @param text
* @param searchString
* @param replacement
* @return java.lang.String
* @Author yujiankai
* @Description StringUtils工具类自带方法 通过StringBuffer
* @date 2021/12/7 16:30
*/
public static String replace(String text, String searchString, String replacement) {
return replace(text, searchString, replacement, -1);
}
private static String replace(String text, String searchString, String replacement, int max, boolean ignoreCase) {
if (!isEmpty(text) && !isEmpty(searchString) && replacement != null && max != 0) {
String searchText = text;
if (ignoreCase) {
searchText = text.toLowerCase();
searchString = searchString.toLowerCase();
}
int start = 0;
int end = searchText.indexOf(searchString, start);
if (end == -1) {
return text;
} else {
//目标词汇长度
int replLength = searchString.length();
//数组长度增量
int increase = replacement.length() - replLength;
increase = increase < 0 ? 0 : increase;
increase *= max < 0 ? 16 : (max > 64 ? 64 : max);
StringBuilder buf;
for(buf = new StringBuilder(text.length() + increase); end != -1; end = searchText.indexOf(searchString, start)) {
//将text 目标词汇前面字段全部拼接入StringBuilder
buf.append(text, start, end).append(replacement);
//替换完成 位置定位到目标词汇之后 end值重新刷新再次循环
start = end + replLength;
--max;
if (max == 0) {
break;
}
}
//添加尾部未被处理字段
buf.append(text, start, text.length());
return buf.toString();
}
} else {
return text;
}
}
执行速度对比测试:
30w条数据分别测试3个工具类,结果如下
很显然,StringUtils自带的工具类速度最快
通过查阅资料可以发现:
- String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间
- StringBuilder 是可变类,速度更快
- 而对于外部找的工具类,我想可能是在每一次赋值操作都是从头开始,时间复杂度较大。另外这个工具类还有个bug,当替换的内容包含目标内容时,就会无限递归,造成栈溢出的问题。
探究具体原因,鉴于我是个小白,希望大佬能指点