我有一个特殊格式的字符串,所以我想将该字符串解析为map。我有一个下面的方法,它将String解析为Map,它工作正常。
public static Map<String, String> parseStringToMap(String payload) {
try {
return Maps.newHashMap(Splitter.on("|").withKeyValueSeparator("=").split(payload));
} catch (Exception ex) {
return ImmutableMap.of();
}
}
字符串示例:
"type=3|Id=23456|user=13456"
现在有时当我在相同的字符串payload
中使用相同的值两次相同的键时,我的上述方法失败并抛出异常。例如,对于下面的字符串,它不起作用,它失败然后返回空映射,因为它有两次type
键。
"type=3|Id=23456|user=13456|type=3"
我该怎么做才能修复此问题而不是修复字符串有效负载?因此,假设相同的密钥多次出现,则覆盖映射中的该键值而不是失败。我想要返回一张Mutable地图。
我仍在使用Java 7.执行此操作的最佳和有效方法是什么?
答案 0 :(得分:1)
我不知道在Guava中如何做到这一点,但用普通的旧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;
如果你想检查字符串是否格式正确(即有管道分隔的元素,每个元素都包含一个=
符号),那么你可以使用indexOf
来查找这些:
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;
}
答案 1 :(得分:0)
文档说如果有重复的密钥,split会抛出异常:
@CheckReturnValue公共地图拆分(CharSequence 序列)
将序列拆分为子字符串,将每个子字符串拆分为一个条目, 并返回每个条目的不可修改的映射。例如, Splitter.on( ';')trimResults()withKeyValueSeparator( “=&gt;” 中)。 .split(“a =&gt; b; c =&gt; b”)将返回从“a”到“b”和“c”的映射到 湾
返回的地图保留了序列中条目的顺序。
抛出: 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));