将字符串内容键/值对映射到HashMap

时间:2010-08-27 10:48:56

标签: java regex

我正在尝试建立一种将String文档映射到HashMap的方法,如下所示:

String包含键/值对

$key1=value1
$key2=value2 value21
value22
$key3=value3

我最终想要的是:

key1, value1
key2, value2 value21\nvalue22
key3, value3

我可以用这个模式吗?它看起来像一个有趣的谜题,到目前为止,我已经想出使用split("[$]{1}[A-Za-z]+[=]{1}")来分隔不同的值,但它必须是一个不同的迭代来识别键,所以我正在寻找一个更优雅的解决方案。

4 个答案:

答案 0 :(得分:1)

您可能会查看Properties个文件。

您可以使用Properties.load(InputStream)从文件中读取条目:

Properties properties = new Properties();
properties.load(this.getClass().getClassLoader()
     .getResourceAsStream("file.properties"));

或甚至来自String:

String myString = new String("first=1");
Properties properties = new Properties();
properties.load(new StringBufferInputStream(myString));

您可以在Properties.load(InputStream) doc。

中找到有关格式化的更多信息

答案 1 :(得分:1)

你必须在这里使用两个正则表达式:
\$(\w+)=((\w+\s*)+)会将值与值分开 (\s+)分割价值。

String input = "$key1=value1\n" +
        "$key2=value2 value21\n" +
        "value22\n" +
        "$key3=value3";

Pattern keyValuePattern = Pattern.compile("\\$(\\w+)=((\\w+\\s*)+)");
Matcher keyValueMatcher = keyValuePattern.matcher(input); // get a matcher object
Map<String, List<String>> map = new HashMap<String, List<String>>();
while (keyValueMatcher.find()) {
    String key = keyValueMatcher.group(1);
    List<String> values;
    values = Arrays.asList(keyValueMatcher.group(2).split("\\s+"));
    //If you want to update your lists later comment the line above and uncomment those two
    //values = new ArrayList<String>();
    //values.addAll(Arrays.asList(keyValueMatcher.group(2).split("\\s+")));

    map.put(key, values);
}

System.out.println(map); // {key3=[value3], key2=[value2, value21, value22], key1=[value1]}

注意:你也可以使用\$(\w+)=(.*)作为正则表达式,它取决于你想要匹配的内容,在上面的例子中,每个单词/数字用空格分隔,在这种情况下是任何东西。

答案 2 :(得分:0)

假设完整的文本是一个字符串(= 逐行读取),那么你可以使用多个拆分:

String input = "$key1=value1\n$key2=value2 value21\nvalue22\n$key3=value3";
String[] lines = input.split("\n");
Map<String, String> map = new HashMap<String, String>();


StringBuilder value = null;
String key = null;
for (String line:lines) {
  if (line.contains('=')) {
    if (key != null) {
      // store the actual k/v pair before starting a new one
      map.put(key, value.toString());
    } else {
      // create a new k/v pair
      String[] temp = line.split("=");
      key = temp[0];
      value = new StringBuilder(temp[1]);
    }
  } else {
    // we have a value that belongs to the last k/v pair
    value.append("\n").append(line);
}
map.put(key, value.toString());

解决方案可能需要进行一些微调,但原则上应该有效。

答案 3 :(得分:0)

您需要清楚完全您的界限和分隔符。在你的例子的情况下,我猜测分隔符是行开头的$,后跟一个“单词”(由\w个字符组成)然后是{{1} }符号。

如果我们做一个简化的假设,并说该行开头的=是分隔符(无论后面是什么),那么我们可以这样做:

$

然后您可以在循环中使用它:

(?xms:    # Switch on "x" (comment-mode), "m" (Allow "^" to mean start of line rather than start-of-input), "s" (dot-all)
   ^ \$   # Match $ at start of line only
   ( [^=]+ )   # Then capture everything until the next '=' (you may want to use \w+ here)
   =           # Skip the =
   (
     (?: 
        (?! \n (?: ^ \$ | \z ) )  # Stop if we reach the \n before the next $ at the start of a line or the \n at the end of the input
        .           # Otherwise accept any character (including \n thanks to dot-all mode)
     )  *
   )    # This will capture everything (excluding the trailing newline) up to the next $ at the start of the line (or all the way to the end of the input)
)

(我根本没有测试任何这个,但它应该让你开始)