我有一个像"key1:value1|prop:id|key3:value3|id:ABC.CDE|key4:value4"
这样的字符串,如何使用Splitter.MapSplitter from Guava分割到id键?
Splitter.MapSplitter.on('|').withKeyValuePairs(':").split()
返回一个不可修改的Map,所以我需要遍历Map直到id键,并在这种情况下将条目放入新Map。它看起来不是一个有效的解决方案。String.substring(0, String.indexOf('|', String.indexOf("id")))
不是一个选项,因为“id”String可以是id键之前的任何值的子字符串。什么是最佳解决方案?
答案 0 :(得分:0)
除了将MapSplitter的输出复制到另一个Map并操纵它(假设键顺序被保留)之外,我认为除了部分解析你之外没有其他解决方案。
您对可能出现在其他地方的“ID”的评论是正确的,因此您需要搜索更具体的内容,例如|id:...|
或id:...|
如果id
是第一个密钥。
private static final Pattern ID_REGEX = Pattern.compile("(^|\\|)id:.+?\\|");
...
Matcher matcher = ID_REGEX.matcher(line);
if (matcher.find()) {
lineForMapSplitter = line.substring(0, matcher.end()-1);
}
答案 1 :(得分:0)
首先,不要直接使用Splitter.MapSplitter
,而应使用Splitter#withKeyValueSeparator
(此处:Splitter.on('|').withKeyValueSeparator(':')
。其次,在您的情况下,最有效的方法是手动拆分对,然后如果你的谓词(关于key == id)不满足,则拆分对,直到最后才创建map。
TIMTOWDI,但我正在使用jOOL,它为您的用例提供了有用的方法。 Seq.seq(Iterable)
是创建流的简单助手,更重要的是,Seq#limitUntilClosed(Predicate)
会在找到id
键之前获取所有值:
private static final Splitter PAIRS_SPLITTER = Splitter.on('|');
private static final Splitter KEY_VALUE_SPLITTER = Splitter.on(':');
private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
private Map<String, String> homebrewMapSplitter(final String string)
{
return Seq.seq(PAIRS_SPLITTER.split(string))
.map(this::createEntry)
.limitUntilClosed(e -> e.getKey().equals("id"))
.collect(ImmutableMap.toImmutableMap(
Map.Entry::getKey,
Map.Entry::getValue)
);
}
// ~copied from MapSplitter#split(CharSequence)
private Map.Entry<String, String> createEntry(final String entry)
{
Iterator<String> entryFields = KEY_VALUE_SPLITTER.split(entry).iterator();
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String key = entryFields.next();
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String value = entryFields.next();
checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
return Maps.immutableEntry(key, value);
}