Java 将格式化字符串解析为多次具有相同键的映射?
我有一个特殊格式的字符串,所以我想将该字符串解析为map。我有一个下面的方法,它可以将字符串解析成一个映射,并且效果很好Java 将格式化字符串解析为多次具有相同键的映射?,java,hashmap,guava,splitter,Java,Hashmap,Guava,Splitter,我有一个特殊格式的字符串,所以我想将该字符串解析为map。我有一个下面的方法,它可以将字符串解析成一个映射,并且效果很好 public static Map<String, String> parseStringToMap(String payload) { try { return Maps.newHashMap(Splitter.on("|").withKeyValueSeparator("=").split(payload)); } catch
public static Map<String, String> parseStringToMap(String payload) {
try {
return Maps.newHashMap(Splitter.on("|").withKeyValueSeparator("=").split(payload));
} catch (Exception ex) {
return ImmutableMap.of();
}
}
现在,有时当我在同一个字符串中有两个相同的键和相同的值时,我的上述方法失败,并抛出异常。例如,对于下面的字符串,它不工作并且失败,然后返回空映射,因为它有两次type
键
"type=3|Id=23456|user=13456|type=3"
我可以做些什么来解决这个问题,而不是解决字符串负载?假设同一个键多次出现,则在映射中覆盖该键值,而不是失败。我想返回一个可变映射
我仍然在使用Java7。最有效的方法是什么?我不知道用番石榴做这件事的方法,但用普通的旧Java做这件事并不难:
Map<String, String> map = new HashMap<>();
for (String part : payload.split("\\|")) {
String[] subparts = part.split("=", 2);
map.put(subparts[0], subparts[1]);
}
return map;
文档说明,如果存在重复的密钥,split将引发异常: @CheckReturnValue公共映射拆分(CharSequence 顺序) 将序列拆分为子字符串,将每个子字符串拆分为一个条目, 并返回每个条目的不可修改映射。例如 Splitter.on(“;”).trimResults().withKeyValueSeparator(“=>”) .split(“a=>b;c=>b”)将返回从“a”到“b”和“c”到“c”的映射 b 返回的映射保留了序列中条目的顺序 抛出: IllegalArgumentException-如果指定的序列未拆分为有效的映射项,或者如果存在重复的键 因此,您不能使用从MapSplitter分割,抱歉 使用Java 8:
return Splitter
.on("|")
.splitToList(payload)
.stream()
.map(kv -> kv.split("="))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv[1], (d1, d2) -> d1));
你能使用Java8吗?如果是这样,您可以使用分组收集器来构建
映射
,或类似的。@AndyTurner不幸的是,我仍然使用Java 7,还不能使用Java 8。通过这种方式,我如何检查它们是否仅为该格式?如果它们不是该格式,则返回空映射?或者我应该用try-catch把它包装起来,如果它们不是那种格式并且基于返回的空映射,它会自动抛出异常吗?你说的“不是那种格式”是什么意思?是否有一个=
,然后是一个|
,然后是一个=
等,中间有字符?当然:只需使用indexof搜索字符串中的内容。是的,它必须是此格式,如果不是,则返回空映射。我尝试了您对此有效负载的编辑建议,该负载的格式无效type=3:Id=23456 | user=13456 | type=3
,并且它不会返回空映射,因为它认为这是一个有效字符串。这不是以什么方式有效吗?它在所有管道之间有一个等号(/字符串的开始和结束)。第一个值中有多个等号并不自动使其无效;这正是你(未说明)的要求。如果这是您想要的,那么为什么不尝试修改此代码呢?这不是一个很难的改变。是的,那么除了Splitter之外还有更好的方法吗?@user1950349也许你可以先用正则表达式修复你的输入?不幸的是,我仍然使用Java 7。
int start = 0;
while (start < payload.length()) {
int end = payload.indexOf('|', start);
if (end == -1) {
end = payload.length();
}
int equalsPos = payload.indexOf('=', start);
if (equalsPos > end || equalsPos < 0) {
// No = found between adjacent |s. Not valid format.
return Collections.emptyMap();
}
// Extract the substrings between | and =, and = and the next |.
map.put(payload.substring(start, equalsPos), payload.substring(equalsPos + 1, end));
start = end + 1;
}
return Splitter
.on("|")
.splitToList(payload)
.stream()
.map(kv -> kv.split("="))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv[1], (d1, d2) -> d1));