我正在尝试建立一种将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}")
来分隔不同的值,但它必须是一个不同的迭代来识别键,所以我正在寻找一个更优雅的解决方案。
答案 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)
)
(我根本没有测试任何这个,但它应该让你开始)