Java 取消设置值的哈希映射
我目前有一个键值对的映射,格式为Java 取消设置值的哈希映射,java,Java,我目前有一个键值对的映射,格式为 a.b.c: value1 e.f: value2 g: [ g.h: nested_value1 g.i: nested_value2 ] 我需要在嵌套结构中将其“展开”到一个新的映射- a: b: c: value1 e: f: value2 g: [ h: nested_value1 i: nested_value2 ] 我当前的尝试没有走多远,抛出了ConcurrentModificationException pri
a.b.c: value1
e.f: value2
g: [
g.h: nested_value1
g.i: nested_value2
]
我需要在嵌套结构中将其“展开”到一个新的映射-
a:
b:
c: value1
e:
f: value2
g: [
h: nested_value1
i: nested_value2
]
我当前的尝试没有走多远,抛出了ConcurrentModificationException
private static Map<String, Object> unflatten(Map<String, Object> flattened) {
Map<String, Object> unflattened = new HashMap<>();
for (String key : flattened.keySet()) {
doUnflatten(flattened, unflattened, key, flattened.get(key));
}
return unflattened;
}
private static Map<String, Object> doUnflatten(
Map<String, Object> flattened,
Map<String, Object> unflattened,
String key,
Object value) {
String[] parts = StringUtils.split(key, '.');
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
Object current = flattened.get(part);
if (i == (parts.length - 1)) {
unflattened.put(part, value);
} else if (current == null) {
if ((current = unflattened.get(part)) == null) {
current = new HashMap<>();
}
unflattened.put(part, current);
unflattened = (Map<String, Object>) current;
} else if (current instanceof Map) {
unflattened.put(part, current);
unflattened = (Map<String, Object>) current;
}
}
return unflattened;
}
private静态映射展开(映射展开){
Map unflatteed=新的HashMap();
for(字符串键:展平.keySet()){
doUnflatten(展平,未展平,键,展平,get(键));
}
不加宣传地返回;
}
私有静态映射doUnflatten(
地图变平,
地图没有平台,
字符串键,
对象值){
String[]parts=StringUtils.split(键“.”);
对于(int i=0;i
我是不是漏掉了什么明显的东西?一种解决方案是使用JSONFlatter这样的库——唯一的问题是这将涉及在JSON之间来回转换
编辑:谢谢你的指点——我已经说到一半了,有一件事我忘了提一下,那就是它还需要取消一组HashMaps的框架你的错误是因为你迭代了密钥集,然后更改了映射,而不是通过迭代器 该类的所有“集合”视图返回的迭代器 方法“是快速失效的:如果地图在任何时候被结构修改 创建迭代器后的时间,以任何方式,除了通过 迭代器自己的remove方法,迭代器将抛出 ConcurrentModificationException。因此,面对同时发生的冲突, 修改后,迭代器会快速、干净地失败,而不是 在不确定的时间冒任意、不确定行为的风险 将来
您可以通过使用新地图来解决此问题。最简单的解决方案是替换线条
for (String key : flattened.keySet()) {
到
for(字符串键:新的ArrayList(flatted.keySet())){
但是,对于大数据量,从性能角度来看,它可能不是非常有效。实现的问题是,您正在将输出写入用于输入的同一个
Map
,这会导致ConcurrentModificationException
通过单独的映射
输出,实现变得简单:
Map<String,Object> unflattened = new HashMap<>();
for (Map.Entry<String,Object> e : flattened.entrySet()) {
String[] parts = StringUtils.split(e.getKey(), ".");
// Find the map to be used as a destination for put(...)
Map<String,Object> dest = unflattened;
for (int i = 0 ; i != parts.length-1 ; i++) {
Object tmp = dest.get(parts[i]);
if (tmp == null) {
// We did not see this branch yet
Map<String,Object> next = new HashMap<>();
dest.put(parts[i], next);
dest = next;
continue;
}
if (!(temp instanceof Map)) {
throw new IllegalStateException();
}
dest = (Map<String,Object>)temp;
}
// Put the entry into the destination Map<>
dest.put(parts[parts.length-1], e.getValue());
}
为您的结果创建一个新的
Map
实例,而不是尝试重用当前实例。另外,请发送Map值,这样就不需要提取:
private static Map<String, Object> unflatten(Map<String, Object> flattened) {
Map<String, Object> unflattened = new HashMap<>();
for (String key : flattened.keySet()) {
doUnflatten(unflattened, key, flattened.get(key));
}
return unflattened;
}
注意事项:无需从方法返回映射。将循环分为两种不同的情况:要么将值写入映射,要么创建或检索嵌套映射。好的,您正在修改迭代的同一对象。也许您应该尝试为每个键创建一个新的hashmap,并将其附加到另一个new hashmap。不需要修改作为参数传递的映射,您可以更改函数来构建并返回一个“未设置”的新映射。是的,刚刚注意到我自己会覆盖值-需要检查该叶是否已经在新映射中!
"a.b.c" -> "x" // OK: "a.b" is a branch
"a.b.d" -> "y" // OK: "a.b" is a branch
"a.b" -> "z" // Error: "a.b" is a leaf
private static Map<String, Object> unflatten(Map<String, Object> flattened) {
Map<String, Object> unflattened = new HashMap<>();
for (String key : flattened.keySet()) {
doUnflatten(unflattened, key, flattened.get(key));
}
return unflattened;
}
private static void doUnflatten(Map<String, Object> current, String key,
Object originalValue) {
String[] parts = StringUtils.split(key, ".");
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (i == (parts.length - 1)) {
current.put(part, originalValue);
return;
}
Map<String, Object> nestedMap = (Map<String, Object>) current.get(part);
if (nestedMap == null) {
nestedMap = new HashMap<>();
current.put(part, nestedMap);
}
current = nestedMap;
}
}