Java字符串解析-{k1=v1,k2=v2,…}
我有以下字符串,可能包含约100个条目:Java字符串解析-{k1=v1,k2=v2,…},java,text-parsing,Java,Text Parsing,我有以下字符串,可能包含约100个条目: String foo = "{k1=v1,k2=v2,...}" 我希望编写以下函数: String getValue(String key){ // return the value associated with this key } 我希望在不使用任何解析库的情况下执行此操作。有什么快速的想法吗?如果你知道你的字符串总是这样的,试试下面的方法: HashMap map = new HashMap(); public void pars
String foo = "{k1=v1,k2=v2,...}"
我希望编写以下函数:
String getValue(String key){
// return the value associated with this key
}
我希望在不使用任何解析库的情况下执行此操作。有什么快速的想法吗?如果你知道你的字符串总是这样的,试试下面的方法:
HashMap map = new HashMap();
public void parse(String foo) {
String foo2 = foo.substring(1, foo.length() - 1); // hack off braces
StringTokenizer st = new StringTokenizer(foo2, ",");
while (st.hasMoreTokens()) {
String thisToken = st.nextToken();
StringTokenizer st2 = new StringTokenizer(thisToken, "=");
map.put(st2.nextToken(), st2.nextToken());
}
}
String getValue(String key) {
return map.get(key).toString();
}
警告:我实际上没有尝试过这个;可能有一些小的语法错误,但逻辑应该是合理的。请注意,我还进行了完全零错误检查,因此您可能希望使我所做的更加健壮。我能想到的最快速但最丑陋的答案是使用状态机逐个字符地解析它。它非常快,但非常具体,非常复杂。在我看来,你可以有几种状态:
- 解析键
- 解析值
- 准备好了吗
int length = foo.length();
int state = READY;
for (int i=0; i<length; ++i) {
switch (state) {
case READY:
//Skip commas and brackets
//Transition to the KEY state if you find a letter
break;
case KEY:
//Read until you hit a = then transition to the value state
//append each letter to a StringBuilder and track the name
//Store the name when you transition to the value state
break;
case VALUE:
//Read until you hit a , then transition to the ready state
//Remember to save the built-key and built-value somewhere
break;
}
}
int length=foo.length();
int状态=就绪;
对于(int i=0;i未经测试写入:
String result = null;
int i = foo.indexOf(key+"=");
if (i != -1 && (foo.charAt(i-1) == '{' || foo.charAt(i-1) == ',')) {
int j = foo.indexOf(',', i);
if (j == -1) j = foo.length() - 1;
result = foo.substring(i+key.length()+1, j);
}
return result;
是的,它很难看:-)好吧,假设值中没有“=”或“,”,最简单(也很糟糕)的方法是:
int start = foo.indexOf(key+'=') + key.length() + 1;
int end = foo.indexOf(',',i) - 1;
if (end==-1) end = foo.indexOf('}',i) - 1;
return (start<end)?foo.substring(start,end):null;
int start=foo.indexOf(key+'=')+key.length()+1;
int end=foo.indexOf(',',i)-1;
如果(end==-1)end=foo.indexOf('}',i)-1;
return(start如果字符串有许多条目,那么最好不用StringTokenizer手动解析以节省一些内存(如果必须解析数千个这样的字符串,那么额外的代码是值得的):
我用这些字符串测试了这段代码,效果很好:
{k1=v1}
{k1=v1,k2=v2,k3=v3,k4=v4}
{k1=v1,}添加代码以检查foo
中是否存在键
,作为练习留给读者:-)
请找到我的解决方案:
public class KeyValueParser {
private final String line;
private final String divToken;
private final String eqToken;
private Map<String, String> map = new HashMap<String, String>();
// user_uid=224620; pass=e10adc3949ba59abbe56e057f20f883e;
public KeyValueParser(String line, String divToken, String eqToken) {
this.line = line;
this.divToken = divToken;
this.eqToken = eqToken;
proccess();
}
public void proccess() {
if (Strings.isNullOrEmpty(line) || Strings.isNullOrEmpty(divToken) || Strings.isNullOrEmpty(eqToken)) {
return;
}
for (String div : line.split(divToken)) {
if (Strings.isNullOrEmpty(div)) {
continue;
}
String[] split = div.split(eqToken);
if (split.length != 2) {
continue;
}
String key = split[0];
String value = split[1];
if (Strings.isNullOrEmpty(key)) {
continue;
}
map.put(key.trim(), value.trim());
}
}
public String getValue(String key) {
return map.get(key);
}
}
我的解析库你是说正则表达式,还是没有第三方库?v1,v2。。。包含“=”或“,”?假设值不包含“=”或“,”。只是没有第三方LIB。这非常接近JSON。为什么不使用它?(另外:Java中没有第三方lib?疯狂。)对于原始速度,使用char数组来避免同步。好吧,这是一个老习惯,因为现代JVM会使锁变粗:-)哦,好主意。实际上我完全忘记了如何访问角色…不要认为我会使用这个,但有趣的答案!哦,我知道这不是好方法:)我只是想表明这是一种快速的方法。但有些用户比我快,以前也发布过类似的解决方案。我在其他答案中也看不到好的解决方案,最终的解决方案意味着使用AST解析器或类似的东西。快捷方式是使用,={}
。无需破解大括号或第二个标记器:)
String foo = "{k1=v1,k2=v2,...}";
String getValue(String key){
int offset = foo.indexOf(key+'=') + key.length() + 1;
return foo.substring(foo.indexOf('=', offset)+1,foo.indexOf(',', offset));
}
public class KeyValueParser {
private final String line;
private final String divToken;
private final String eqToken;
private Map<String, String> map = new HashMap<String, String>();
// user_uid=224620; pass=e10adc3949ba59abbe56e057f20f883e;
public KeyValueParser(String line, String divToken, String eqToken) {
this.line = line;
this.divToken = divToken;
this.eqToken = eqToken;
proccess();
}
public void proccess() {
if (Strings.isNullOrEmpty(line) || Strings.isNullOrEmpty(divToken) || Strings.isNullOrEmpty(eqToken)) {
return;
}
for (String div : line.split(divToken)) {
if (Strings.isNullOrEmpty(div)) {
continue;
}
String[] split = div.split(eqToken);
if (split.length != 2) {
continue;
}
String key = split[0];
String value = split[1];
if (Strings.isNullOrEmpty(key)) {
continue;
}
map.put(key.trim(), value.trim());
}
}
public String getValue(String key) {
return map.get(key);
}
}
KeyValueParser line = new KeyValueParser("user_uid=224620; pass=e10adc3949ba59abbe56e057f20f883e;", ";", "=");
String userUID = line.getValue("user_uid")