Java 字符串解析 - {k1=v1,k2=v2,...}

发布于 2024-08-09 03:39:57 字数 255 浏览 4 评论 0原文

我有以下字符串,可能包含 ~100 个条目:

String foo = "{k1=v1,k2=v2,...}"

并且我希望编写以下函数:

String getValue(String key){
    // return the value associated with this key
}

我想在不使用任何解析库的情况下执行此操作。有什么快速的想法吗?

I have the following string which will probably contain ~100 entries:

String foo = "{k1=v1,k2=v2,...}"

and am looking to write the following function:

String getValue(String key){
    // return the value associated with this key
}

I would like to do this without using any parsing library. Any ideas for something speedy?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

嘴硬脾气大 2024-08-16 03:39:57

如果您知道您的字符串总是这样,请尝试以下操作:

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();
}

警告:我实际上并没有尝试过这个;可能会有轻微的语法错误,但逻辑应该是合理的。请注意,我还进行了完全零错误检查,因此您可能想让我所做的更加稳健。

If you know your string will always look like this, try something like:

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();
}

Warning: I didn't actually try this; there might be minor syntax errors but the logic should be sound. Note that I also did exactly zero error checking, so you might want to make what I did more robust.

怎言笑 2024-08-16 03:39:57

我能想到的最快但最丑陋的答案是使用状态机逐个字符地解析它。它非常快,但非常具体且相当复杂。在我看来,您可能有几种状态:

  • 解析键
  • 解析值
  • 就绪

示例:

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;
   }
}

此外,您可以使用 StringTokenizers(速度较快)或 Regex(速度较慢)更快地实现此目的。但总的来说,单个字符解析很可能是最快的方法。

The speediest, but ugliest answer I can think of is parsing it character by character using a state machine. It's very fast, but very specific and quite complex. The way I see it, you could have several states:

  • Parsing Key
  • Parsing Value
  • Ready

Example:

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;
   }
}

In addition, you can implement this a lot faster using StringTokenizers (which are fast) or Regexs (which are slower). But overall, individual character parsing is most likely the fastest way.

々眼睛长脚气 2024-08-16 03:39:57

如果字符串有很多条目,您可能最好在不使用 StringTokenizer 的情况下手动解析以节省一些内存(如果您必须解析数千个这些字符串,则值得额外的代码):


public static Map parse(String s) {
    HashMap map = new HashMap();
    s = s.substring(1, s.length() - 1).trim(); //get rid of the brackets
    int kpos = 0; //the starting position of the key
    int eqpos = s.indexOf('='); //the position of the key/value separator
    boolean more = eqpos > 0;
    while (more) {
        int cmpos = s.indexOf(',', eqpos + 1); //position of the entry separator
        String key = s.substring(kpos, eqpos).trim();
        if (cmpos > 0) {
            map.put(key, s.substring(eqpos + 1, cmpos).trim());
            eqpos = s.indexOf('=', cmpos + 1);
            more = eqpos > 0;
            if (more) {
                kpos = cmpos + 1;
            }
        } else {
            map.put(key, s.substring(eqpos + 1).trim());
            more = false;
        }
    }
    return map;
}

我使用这些字符串测试了此代码,它工作正常:

{k1=v1}

{k1=v1, k2 = v2, k3= v3,k4 =v4}

{k1= v1,}

If the string has many entries you might be better off parsing manually without a StringTokenizer to save some memory (in case you have to parse thousands of these strings, it's worth the extra code):


public static Map parse(String s) {
    HashMap map = new HashMap();
    s = s.substring(1, s.length() - 1).trim(); //get rid of the brackets
    int kpos = 0; //the starting position of the key
    int eqpos = s.indexOf('='); //the position of the key/value separator
    boolean more = eqpos > 0;
    while (more) {
        int cmpos = s.indexOf(',', eqpos + 1); //position of the entry separator
        String key = s.substring(kpos, eqpos).trim();
        if (cmpos > 0) {
            map.put(key, s.substring(eqpos + 1, cmpos).trim());
            eqpos = s.indexOf('=', cmpos + 1);
            more = eqpos > 0;
            if (more) {
                kpos = cmpos + 1;
            }
        } else {
            map.put(key, s.substring(eqpos + 1).trim());
            more = false;
        }
    }
    return map;
}

I tested this code with these strings and it works fine:

{k1=v1}

{k1=v1, k2 = v2, k3= v3,k4 =v4}

{k1= v1,}

意中人 2024-08-16 03:39:57

未经测试就写的:

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;

是的,它很丑:-)

Written without testing:

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;

Yes, it's ugly :-)

一向肩并 2024-08-16 03:39:57

好吧,假设值中没有“=”或“,”,最简单(且破旧)的方法是:

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;

是的,不推荐:)

Well, assuming no '=' nor ',' in values, the simplest (and shabby) method is:

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;

Yeah, not recommended :)

窗影残 2024-08-16 03:39:57

添加代码来检查 foo 中是否存在 key 留给读者作为练习:-)

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));
}

Adding code to check for existance of key in foo is left as exercise to the reader :-)

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));
}
花间憩 2024-08-16 03:39:57

请找到我的解决方案:

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")

Please find my solution:

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);
    }
}

Usage

KeyValueParser line = new KeyValueParser("user_uid=224620; pass=e10adc3949ba59abbe56e057f20f883e;", ";", "=");
String userUID = line.getValue("user_uid")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文