将key = value的字符串解析为Map

时间:2018-07-11 14:31:37

标签: java regex xml string hashmap

我正在使用一种API,该API为我提供了XML,我需要从一个实际上是字符串的标记中获取一张地图。示例:

拥有

Billable=7200,Overtime=false,TransportCosts=20$

我需要

["Billable"="7200","Overtime=false","TransportCosts"="20$"]

问题在于字符串是完全动态的,因此它可能像

Overtime=true,TransportCosts=one, two, three
Overtime=true,TransportCosts=1= 1,two, three,Billable=7200

所以我不能只用逗号然后用等号分开。 是否可以使用正则表达式将类似字符串的内容转换为地图?

到目前为止,我的代码是:

private Map<String, String> getAttributes(String attributes) {
    final Map<String, String> attr = new HashMap<>();
    if (attributes.contains(",")) {
        final String[] pairs = attributes.split(",");
        for (String s : pairs) {
            if (s.contains("=")) {
                final String pair = s;
                final String[] keyValue = pair.split("=");
                attr.put(keyValue[0], keyValue[1]);
            }
        }
        return attr;
    }
    return attr;
}

提前谢谢

4 个答案:

答案 0 :(得分:2)

您可以使用

(\w+)=(.*?)(?=,\w+=|$)

请参见regex demo

详细信息

  • (\w+)-第1组:一个或多个单词字符
  • =-等号
  • (.*?)-第2组:除换行符以外的任何零个或多个字符,并且尽可能少
  • (?=,\w+=|$)-一个正向的超前查询,需要先输入,,然后输入1个以上的字符,然后输入=,或当前位置右边的字符串结尾。
  • li>

Java代码:

public static Map<String, String> getAttributes(String attributes) {
    Map<String, String> attr = new HashMap<>();
    Matcher m = Pattern.compile("(\\w+)=(.*?)(?=,\\w+=|$)").matcher(attributes);
    while (m.find()) {
        attr.put(m.group(1), m.group(2));
    }
    return attr;
}

Java test

String s = "Overtime=true,TransportCosts=1= 1,two, three,Billable=7200";
Map<String,String> map = getAttributes(s);
for (Map.Entry entry : map.entrySet()) {
    System.out.println(entry.getKey() + "=" + entry.getValue());
}

结果:

Overtime=true
Billable=7200
TransportCosts=1= 1,two, three

答案 1 :(得分:1)

我注意到的第一件事是,很难用您提供的数据来识别定界符,但是似乎可以识别的是,逗号和大写字母将每个字段分开。

这允许使用String.replaceAll("(?<=,)([A-Z])", ",$1")将定界符更改为使用正则表达式可轻松识别的内容。现在,您将有一个定界符,可以识别(,,)并拆分数据以在需要的地方插入引号。

类似的东西:

public class StackOverflow {
    public static void main(String[] args) {
        String [] data = {
                "Overtime=true,TransportCosts=one, two, three",
                "Overtime=true,TransportCosts=1= 1,two, three,Billable=7200"
        };

        for (int i = 0; i < data.length; i++) {
            data[i] = data[i].replaceAll("(?<=,)([A-Z])", ",$1");
            String[] pieces = data[i].split(",,");
            for (int j = 0; j < pieces.length; j++) {
                int equalIndex = pieces[j].indexOf("=");
                StringBuilder sb = new StringBuilder(pieces[j]);
                // Insert quotes around the = sign
                sb.insert(equalIndex, "\"");
                sb.insert(equalIndex + 2, "\"");
                // Insert quotes at the beginning and end of the string
                sb.insert(0, "\"");
                sb.append("\"");
                pieces[j] = sb.toString();              
            }

            // Join the pieces back together delimited by a comma
            data[i] = String.join(",", pieces);
            System.out.println(data[i]);
        }
    }
}

结果

"Overtime"="true","TransportCosts"="one, two, three"
"Overtime"="true","TransportCosts"="1= 1,two, three","Billable"="7200"

答案 2 :(得分:0)

恕我直言,更简单的正则表达式:([^,]+=[^=]+)(,|$)

([^,]+=[^=]+)→分组:除逗号外,后跟1个等号,后跟除等号外的所有内容...
(,|$)→... ...以逗号或行尾分隔

测试:

public static void main(String[] args) {
    Pattern pattern = Pattern.compile("([^,]+=[^=]+)(,|$)");

    String test1 = "abc=def,jkl,nm=ghi,egrh=jh=22,kdfka,92,kjasd=908@0982";
    System.out.println("Test 1: "+test1);
    Matcher matcher = pattern.matcher(test1);
    while (matcher.find()) {
        System.out.println(matcher.group(1));
    }
    System.out.println();
    String test2 = "Overtime=true,TransportCosts=1= 1,two, three,Billable=7200";
    System.out.println("Test 2: "+test2);
    matcher = pattern.matcher(test2);
    while (matcher.find()) {
        System.out.println(matcher.group(1));
    }
}

输出:

  

Test 1: abc=def,jkl,nm=ghi,egrh=jh=22,kdfka,92,kjasd=908@0982
  abc=def,jkl
  nm=ghi
  egrh=jh=22,kdfka,92
  kjasd=908@0982

     

Test 2: Overtime=true,TransportCosts=1= 1,two, three,Billable=7200
  Overtime=true
  TransportCosts=1= 1,two, three
  Billable=7200

答案 3 :(得分:0)

我使用番石榴看到了这段代码

import com.google.common.base.Splitter;


/**
 *  parse string 'prop1=val1; prop2=val2' to map
 */
 public static Map<String, String> parseMap(final String keyValueString) {
     if (StringUtils.isEmpty(keyValueString)) return Collections.emptyMap();

      return Splitter.on(";")
            .trimResults()
            .withKeyValueSeparator('=')
            .split(keyValueString);
}

一个便笺,Idea显示警告,因为Splitter带有注释 com.google.common.annotations.Beta不错,但是在guava库版本更新期间可能需要一些工作。