java批量替换字符串_#Java⼀步⼀步实现⾼逼格的字符串替换
⼯具(⼆)
Java ⼀步⼀步实现⾼逼格的字符串替换⼯具(⼆)
上⼀篇实现了⼀个⽤于字符串替换的⽅法,主要是利⽤ 正则 + jdk的字符串替换,本篇则会再之前的基础上⾛⼀个扩展
1. 之前的⽅法存在的问题
先把上⼀篇的两个⽅法贴下,研究下有什么问题,然后再看下可以怎么去改进
// 获取patter的过程较为负责,这⾥初始化时,做⼀次即可
private static Pattern pattern;
static {
pattern = Patternpile("((?<=\\{)([a-zA-Z_]{1,})(?=\\}))");
}
/**
* 字符串替换, 将 {} 中的内容, ⽤给定的参数进⾏替换
*
* @param text
* @param params
* @return
*/
public static String format(String text, Map params) {
// 把⽂本中的所有需要替换的变量捞出来, 丢进keys
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
String key = up();
// text = place(text, "{" + key + "}", (key) + "");
text = placeAll("\\{" + key + "\\}", (key) + "");
}
return text;
}
public static List batchFormat(String text, List> params) {
List keys = new ArrayList<>();
// 把⽂本中的所有需要替换的变量捞出来, 丢进keys
Matcher matcher = pattern.matcher(text);
int tempIndex = 0;
while (matcher.find()) {
String key = up();
if (ains(key)) {
continue;
}
text = place(text, key, tempIndex + "");
tempIndex++;
keys.add(key);
}
List result = new ArrayList<>(params.size());
String[] tempParamAry = new String[keys.size()];
for (Map param : params) {
for (int i = 0; i < keys.size(); i++) {
tempParamAry[i] = ((i)) + "";
}
result.add(MessageFormat.format(text, tempParamAry));
}
return result;
}
⼀个单个替换,⼀个批量替换,我们⼀个⼀个分析,⾸先看
1. public static String format(String text, Map params)
正则替换效率问题
apache的 commons-lang 有个 StringUtils ⼯具类, 我们可以⽤⾥⾯的 replace ⽅法进⾏代替, 上⾯注释的就是我们推荐的使⽤⽅式
2. public static List batchFormat(String text, List> params)
这个的实现原理⽐较简单
先⽤正则把所有需要替换的捞出来, 放在列表中, 并将坑位⽤数字来替换
java replace方法然后使⽤ MessageFormat.format 进⾏替换
这个流程⽐较清晰简单,对于 MessageFormat.format 却发现⼀个诡异的问题,当text中包含单引号时,后⾯的不会被替换, 测试case如下
public String replace(String text, args) {
return MessageFormat.format(text, args);
}
@Test
public void testReplace2() {
String text = "hello {0}, welcome to {1}!";
String user = "Lucy";
String place = "China";
String ans = replace(text, user, place);
System.out.println(ans);
text = "hello {0}, welcome to {2} ! what's a good day! today is {1}!";
ans = replace(text, "Lucy", new Date(), "HangZhou");
System.out.println(ans);
}
输出如下:
debug到源码去看下,然后发现在⽣成 MessageFormat对象的实现中,单引号内部有特殊⽤途,认为两个单引号之间的为⼀个整体,不做替换
String text = "hello {0}, welcome to {2} ! what's {0}' a good day! today is {1}!";
String ans = MessageFormat.format(text, "Lucy", new Date(), "HangZhou");
System.out.println(ans); // 输出 hello Lucy, welcome to HangZhou ! whats {0} a good day! today is 17-3-28 下午5:54!
2. 改进++
对上⾯的正则获取key,然后再调⽤ MessageFormat.format()的⽅式不满意,特别是后者的潜规则还不少,我们要实现⼀个纯粹的,⾼效的,可扩展的替换⼯具,应该这么玩?
既然已经深⼊了MessageFormat的源码,那么就简单了,把他的实现逻辑抠出来,砍掉各种潜规则,我们⾃⼰来实现即可
新版的设计思路:
- ⾸先将⽂本进⾏拆分
- 以`{}`作为分割, ⼤括号前后的各⾃作为新的`Word`; ⼤括号内的也作为独⽴的`Word`
- 将拆分的`Word` 塞⼊⼀个数组中
- 遍历上⾯的数组,替换变量
- 返回想要的结果
实现如下:
public static String formatV2(String text, Map params) {
StringBuilder stringBuilder = new StringBuilder();
int startIndex = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '{') {
if (startIndex > 0) {
stringBuilder.append(text.substring(startIndex, i));
}
startIndex = i + 1;
continue;
}
if (text.charAt(i) == '}') {
stringBuilder.(text.substring(startIndex, i))); startIndex = i + 1;
}
}
if (startIndex < text.length()) {
stringBuilder.append(text.substring(startIndex));
}
String();
}
/**
* 规定⼤括号中不能再次出现⼤括号, 即不允许迭代替换
*
* @param text
* @param paramsList
* @return
*/
public static List batchFormatV2(String text, List> paramsList) { List textList = splitText2words(text);
List result = new ArrayList<>();
StringBuilder stringBuilder;
for (Map params: paramsList) {
stringBuilder = new StringBuilder();
for (Word word: textList) {
stringBuilder.append(replaceWord(word, params));
}
result.String());
}
return result;
}
private static String replaceWord(Word word, Map params) { if (IsReplaceKey()) {
(Word()) + "";
} else {
Word();
}
}
/**
* 将⽂本根据{}进⾏分割
*
* 如: {place} is a good place, what do you think {user}?
* 分割:
* - Word("place", true)
* - Word(" is a good place, what do you think ", false)
* - Word("user", true)
* - Word("?", false)
*
* @param text
* @return
*/
private static List splitText2words(String text) {
List textList = new ArrayList<>();
int startIndex = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '{') {
if (startIndex > 0) {
textList.add(new Word(text.substring(startIndex, i), false)); }
startIndex = i + 1;
continue;
}
if (text.charAt(i) == '}') {
textList.add(new Word(text.substring(startIndex, i), true));

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。