代码之家  ›  专栏  ›  技术社区  ›  KJW

java:如何将此字符串转换为ArrayList?

  •  0
  • KJW  · 技术社区  · 14 年前
    String text = '[["item1","item2","item3"], ["some", "item"], ["far", "out", "string"]]';
    

    我想遍历每个单独的ArrayList。我不知道如何将该字符串转换为适当的ArrayList对象。

    4 回复  |  直到 14 年前
        1
  •  4
  •   Stephen C    14 年前

    这个语法看起来像JSON的一个子集,我猜客户端实际上是将其编码为JSON。假设这是真的,最简单的方法是使用现成的JSON解析器和一些简单的Java代码来将生成的对象转换为代码所需的形式。

    当然,您可以手工实现自己的解析器,但这可能不值得这么做,特别是如果您必须处理字符串转义、空格中可能存在的变化等等。不要忘记,如果您实现了自己的解析器,那么 需要实现单元测试

    在继续之前,您确实需要确认客户机发送给您的确切语法。仅仅看一个例子并不能回答这个问题。您要么需要一个指定语法的文档,要么需要查看客户机/应用程序源代码。

        2
  •  3
  •   Mark Elliot    14 年前

    这里有一个简单的解析器,它应该处理所有类型的滥用嵌套,并且对单引号和双引号都很健壮——但是如果您将它们混合在一起,它不会在意 'test" 等同于 "test" .

    编辑:添加了注释,现在它处理字符串中的转义引号。(现在改进了字符串令牌处理)

    import java.io.IOException;
    import java.io.StringReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class StringToList {
    
        public static void main(String[] args) throws IOException{
            StringReader sr = new StringReader("[[\"it\\\"em1\", \"item2\",\"item3\"], [\"some\",\"item\"], [\"far\",\"out\",\"string\"]]");
            System.out.println(tokenize(sr));
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static List tokenize(StringReader in) throws IOException{
            List stack = new ArrayList<Object>();
            int c;
            while((c = in.read()) != -1){
                switch(c){
                case '[':
                    // found a nested structure, recurse..
                    stack.add(tokenize(in));
                    break;
                case ']':
                    // found the end of this run, return the
                    // current stack
                    return stack;
                case '"':
                case '\'':
                    // get the next full string token
                    stack.add(stringToken(in));
                    break;
                }
            }
    
            // we artificially start with a list, though in principle I'm
            // defining the string to hold only a single list, so this
            // gets rid of the one I created artifically.
            return (List)stack.get(0);
        }
    
        public static String stringToken(StringReader in) throws IOException{
            StringBuilder str = new StringBuilder();
            boolean escaped = false;
            int c;
            outer: while((c = in.read()) != -1){
                switch(c){
                case '\\':
                    escaped = true;
                    break;
                case '"':
                case '\'':
                    if(escaped){
                        escaped = false;
                    }else{
                        break outer;
                    }
                default:
                    str.append((char)c);
                }
            }
            return str.toString();
        }
    
    }
    

    注意:这不会强制你的语法正确,所以如果你像我描述的那样,用引号做一些愚蠢的事情,它可能仍然会被解析为(不)预期的。另外,我在al不强制使用逗号,引号之间甚至不需要空格,所以 ["item1""item2"] ["item1", "item2"] ,但更奇怪的是,这件事也应该处理 ["item1"asdf"item2"] 忽略 asdf

        3
  •  2
  •   ekaqu    14 年前

    因为您使用的字符串看起来像JSON,所以我只使用JSON解析器。最简单的用法之一是gson。下面是使用gson的示例:

    String text = '[["item1","item2","item3"], ["some", "item"], ["far", "out", "string"]]';
    GSON gson = new GSON();
    ArrayList<ArrayList<String>> list = gson.fromJson(text, new TypeToken<ArrayList<ArrayList<String>>>() {}.getType());
    

    这是gson网站: http://code.google.com/p/google-gson/

        4
  •  -2
  •   usr-local-ΕΨΗΕΛΩΝ    14 年前

    您需要手工构建一个解析器。这不难,但需要时间。

    只需逐个字符解析字符串,并通过首先定义递归解析规则来识别每个标记。递归后代解析器规则通常是图形化的,但是我可以尝试为您使用ABNF

    LIST = NIL / LIST_ITEM *( ',' SP LIST_ITEM)
    LIST_ITEM = NIL / '[' STRING_ITEM *(, SP STRING ITEM) ']'
    STRING_ITEM = '"' ANYCHAR '"'
    SP = space
    ANYCHAR = you know, anything that is not double quotes
    NIL = ''
    

    另一种方法是使用正则表达式。这是几个样品。首先通过

    (\[[^\]]*\])
    

    上面的正则表达式捕获从“[”到第一个“]”的所有内容,但您需要修改它或从字符串中剪切方括号(只需删除第一个和最后一个字符)

    然后通过

    (\"[^\"]\")
    

    简单如上图