Hashmap 将相同的键 "m" 替换为 "mL" ,是否有办法修复它?
Hashmap replace the same key "m" as "mL" , is there anyway to fix it?
我有这个数学表达式:
String exp = "k+(mP/P+mL/L)";
然后我创建一个新的 HashMap 并放入与上述表达式完全相同的参数:
Map<String, Integer> mp = new HashMap<>();
mp.put("k", 1);
mp.put("mP", 2);
mp.put("P", 3);
mp.put("mL", 4);
mp.put("L", 5);
最后,我通过将表达式的参数替换为值继续对所有条目集进行乱码处理,然后打印结果:
for(Map.Entry<String,Integer> e: mp.entrySet()){
exp = exp.replace(e.getKey(),e.getValue().toString());
}
System.out.println(exp);
上面的结果是:“1+(m3/3 +m5/5)”
*但我想要这个:“1+(2/3+4/5)”
有什么办法吗?
使用正则表达式 replaceAll with word-boundary \b
.
exp = exp.replaceAll("\b" + e.getKey() + "\b", e.getValue().toString());
您还可以查看 脚本 API 或 java REPL.
问题是因为HashMap没有保持插入顺序。使用保持插入顺序的LinkedHashMap将解决问题。
Map<String, Integer> mp = new LinkedHashMap<>();
String.replace() 替换所有出现的子字符串,因此如果 P
在 mP
之前被替换,可能会导致您所描述的问题。为避免这种情况,您可以使用没有常用字母的占位符构建表达式。例如:
String exp = "a+(b/c+d/e)";
您还可以按长度对键进行排序:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public static void main(String[] args) {
String exp = "k+(mP/P+mL/L)";
Map<String, Integer> mp = new HashMap<String, Integer>();
mp.put("mP", 2);
mp.put("mL", 4);
mp.put("k", 1);
mp.put("P", 3);
mp.put("L", 5);
String[] keys = new String[mp.keySet().size()];
int i = 0;
for (String k : mp.keySet()) {
keys[i] = k;
i++;
}
/* Sort array by string length (longest string at the beginning) */
Arrays.sort(keys, (a, b) -> Integer.compare(b.length(), a.length()));
for (String k : keys) {
exp = exp.replace(k, mp.get(k).toString());
}
System.out.println(exp); // 1+(2/3+4/5)
}
示例代码。
mp.entrySet()
.stream()
.sorted(Comparator.comparingInt(entry -> entry.getKey().length() * -1))
.forEach((entry) -> exp[0] = exp[0].replace(entry.getKey(),entry.getValue().toString())
);
我有这个数学表达式:
String exp = "k+(mP/P+mL/L)";
然后我创建一个新的 HashMap 并放入与上述表达式完全相同的参数:
Map<String, Integer> mp = new HashMap<>();
mp.put("k", 1);
mp.put("mP", 2);
mp.put("P", 3);
mp.put("mL", 4);
mp.put("L", 5);
最后,我通过将表达式的参数替换为值继续对所有条目集进行乱码处理,然后打印结果:
for(Map.Entry<String,Integer> e: mp.entrySet()){
exp = exp.replace(e.getKey(),e.getValue().toString());
}
System.out.println(exp);
上面的结果是:“1+(m3/3 +m5/5)”
*但我想要这个:“1+(2/3+4/5)”
有什么办法吗?
使用正则表达式 replaceAll with word-boundary \b
.
exp = exp.replaceAll("\b" + e.getKey() + "\b", e.getValue().toString());
您还可以查看 脚本 API 或 java REPL.
问题是因为HashMap没有保持插入顺序。使用保持插入顺序的LinkedHashMap将解决问题。
Map<String, Integer> mp = new LinkedHashMap<>();
String.replace() 替换所有出现的子字符串,因此如果 P
在 mP
之前被替换,可能会导致您所描述的问题。为避免这种情况,您可以使用没有常用字母的占位符构建表达式。例如:
String exp = "a+(b/c+d/e)";
您还可以按长度对键进行排序:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public static void main(String[] args) {
String exp = "k+(mP/P+mL/L)";
Map<String, Integer> mp = new HashMap<String, Integer>();
mp.put("mP", 2);
mp.put("mL", 4);
mp.put("k", 1);
mp.put("P", 3);
mp.put("L", 5);
String[] keys = new String[mp.keySet().size()];
int i = 0;
for (String k : mp.keySet()) {
keys[i] = k;
i++;
}
/* Sort array by string length (longest string at the beginning) */
Arrays.sort(keys, (a, b) -> Integer.compare(b.length(), a.length()));
for (String k : keys) {
exp = exp.replace(k, mp.get(k).toString());
}
System.out.println(exp); // 1+(2/3+4/5)
}
示例代码。
mp.entrySet()
.stream()
.sorted(Comparator.comparingInt(entry -> entry.getKey().length() * -1))
.forEach((entry) -> exp[0] = exp[0].replace(entry.getKey(),entry.getValue().toString())
);