我使用org.apache.commons.lang3.text.StrSubstitutor来解析String。我有类似的设置:
StrSubstitutor sub = new StrSubstitutor(messageValues, "&(", ")");
String format = sub.replace("Information: &(killer) killed &(target)!");
如果我在不同情况下使用密钥,则此功能不再有效:
"Information: &(KILLER) killed &(TARGET)!"
有没有办法为String Substitutor 不区分大小写制作密钥?
我无法使用toLowerCase()
,因为我只希望密钥不区分大小写。
答案 0 :(得分:3)
StrSubstitutor有一个构造函数,它接受一个StrLookup实例。您可以创建一个StrLookup实现,在实际查找它们之前降低其查找的键。
以下是它的样子:
public class CaseInsensitiveStrLookup<V> extends StrLookup<V> {
private final Map<String, V> map;
CaseInsensitiveStrLookup(final Map<String, V> map) {
this.map = map;
}
@Override
public String lookup(final String key) {
String lowercaseKey = key.toLowerCase(); //lowercase the key you're looking for
if (map == null) {
return null;
}
final Object obj = map.get(lowercaseKey);
if (obj == null) {
return null;
}
return obj.toString();
}
}
使用此StrLookup实现,您无需担心要传递给构造函数的Map类型。
以下测试用例使用上述实现成功返回:
import org.apache.commons.lang3.text.StrSubstitutor;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.HashMap;
import java.util.Map;
@Test
public class TestClass {
@Test
public void test() {
Map<String, String> messageValues = new HashMap<String, String>();
messageValues.put("killer", "Johnson");
messageValues.put("target", "Quagmire");
StrSubstitutor sub = new StrSubstitutor(new CaseInsensitiveStrLookup<String>(messageValues), "&(", ")", '\\');
String format2 = sub.replace("Information: &(killer) killed &(target)!");
String format = sub.replace("Information: &(KILLER) killed &(TARGET)!");
Assert.assertEquals(format, "Information: Johnson killed Quagmire!");
Assert.assertEquals(format2, "Information: Johnson killed Quagmire!");
}
}
答案 1 :(得分:3)
您不需要编写自定义类。假设您可以使用日志( n )访问时间,只需使用不区分大小写的TreeMap。
public static void main(String[] args) {
Map<String, String> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
m.put("foo", "bar");
StrSubstitutor sub = new StrSubstitutor(m);
String s = sub.replace("${FOO}");
System.out.println(s);
} // prints "bar"
答案 2 :(得分:1)
我认为这个不区分大小写的地图会起作用:
import java.util.HashMap;
import java.util.Map;
public class CaseMap<V> extends HashMap<String, V> {
public CaseMap() {
}
public CaseMap(int capacity) {
super(capacity);
}
public CaseMap(int capacity, float loadFactor) {
super(capacity, loadFactor);
}
public CaseMap(Map<String, ? extends V> map) {
putAll(map);
}
public V put(String key, V value) {
return super.put(key.toUpperCase(), value);
}
public V get(Object key) {
if (!(key instanceof String)) return null;
return super.get(((String)key).toUpperCase());
}
}
如果您不控制messageValues地图的创建,您可以像这样构建一个CaseMap:
CaseMap<String> caseFreeMessageValues = new CaseMap<String>(messageValues);
然后像这样构建你的StrSubstitutor:
StrSubstitutor sub = new StrSubstitutor(messageValues, "&(", ")");
String format = sub.replace("Information: &(KILLER) killed &(TARGET)!");
您可能想要考虑应该覆盖的Map
的其他方法,例如containsKey
。
答案 3 :(得分:0)
如果你需要灵活性,Map和Tokens都不区分大小写并且你无法控制正在构建的地图,你可以使用这样的东西。
String replaceTokens(String str, Map<String, String> messageValues) {
if(tokenToValue == null || tokenToValue.size() < 1) return str;
StrSubstitutor caseInsensitiveTokenReplacer = new StrSubstitutor(new CaseInsensitiveStrLookup<>(messageValues),
"&(", ")", '\\');
return caseInsensitiveTokenReplacer.replace(str);
}
StrLookup实施
public class CaseInsensitiveStrLookup<V> extends StrLookup<V> {
private final Map<String, V> map = new TreeMap<String, V>(String.CASE_INSENSITIVE_ORDER);
public CaseInsensitiveStrLookup(final Map<String, V> map) throws NullValueKeyNotSupported {
if(map.containsKey(null)) throw new Exception(); // Dont want to support null
this.map.putAll(map);
}
@Override
public String lookup(final String key) {
V value = map.get(key);
if(value == null) return null;
return value.toString();
}}