I have a flat map of type Map<String, String>
from which I would like to restore the original value tree Map<String, Object>
. Elements of the tree can be either Map<String, Object>
, or List<Object>
, or simply String
. The depth of the tree is not limited. For example:
public static void main(String[] args) {
TreeMap<String, String> flatMap = new TreeMap<String, String>() {{
put("1999.3:1", "23");
put("1999.3:2", "24");
put("1999.3:3", "25");
put("1999.4:1", "1");
put("1999.4:2", "2");
put("1999.4:3.10", "42");
put("2001.11.7:1", "23");
put("2001.11.7:2", "24");
put("2001.11.7:3", "25");
put("2001.11.9:1", "1");
put("2001.11.9:2", "2");
put("2001.11.9:3", "3");
put("2001.12", "45");
}};
System.out.println(flatMap);
}
Flat map:
{1999.3:1=23, 1999.3:2=24, 1999.3:3=25, 1999.4:1=1, 1999.4:2=2, 1999.4:3.10=42,
2001.11.7:1=23, 2001.11.7:2=24, 2001.11.7:3=25,
2001.11.9:1=1, 2001.11.9:2=2, 2001.11.9:3=3, 2001.12=45}
Original value tree:
{1999={3=[23, 24, 25], 4=[1, 2, {10=42}]},
2001={11={7=[23, 24, 25], 9=[1, 2, 3]}, 12=45}}
Opposite: Flatten nested Map containing with unknown level of nested Arrays and Maps recursively.
Iterate over flat map keys and restore original tree. For each key left to right find delimiter characters:
.
- nested object is a map. The next number is the key in the map.:
- nested object is a list. The next number is the index in the list (starts fom 1
).Then recursively process nested objects, shifting to the right by the key of the flat map:
public static void main(String[] args) {
TreeMap<String, String> flatMap = new TreeMap<String, String>() {{
put("1999.3:1", "23");
put("1999.3:2", "24");
put("1999.3:3", "25");
put("1999.4:1", "1");
put("1999.4:2", "2");
put("1999.4:3.10", "42");
put("2001.11.7:1", "23");
put("2001.11.7:2", "24");
put("2001.11.7:3", "25");
put("2001.11.9:1", "1");
put("2001.11.9:2", "2");
put("2001.11.9:3", "3");
put("2001.12", "45");
}};
TreeMap<String, Object> originalMap = new TreeMap<>();
flatMap.forEach((key, value) -> processMap(key, value, originalMap));
System.out.println(flatMap);
System.out.println(originalMap);
}
@SuppressWarnings("unchecked")
private static void processMap(String flatMapKey,
String flatMapValue,
Map<String, Object> map) {
int dot = flatMapKey.indexOf('.');
int colon = flatMapKey.indexOf(':');
// nested map
if (dot > -1 && (dot < colon || colon == -1)) {
String key = flatMapKey.substring(0, dot);
Object nestedMap = map.get(key);
if (nestedMap == null) {
map.put(key, new TreeMap<>());
}
nestedMap = map.get(key);
processMap(flatMapKey.substring(dot + 1),
flatMapValue, (Map<String, Object>) nestedMap);
}
// nested list
else if (colon > -1 && (colon < dot || dot == -1)) {
String key = flatMapKey.substring(0, colon);
Object nestedList = map.get(key);
if (nestedList == null) {
map.put(key, new ArrayList<>());
}
nestedList = map.get(key);
processList(flatMapKey.substring(colon + 1),
flatMapValue, (List<Object>) nestedList);
}
// insert value
else if (dot == colon) {
map.put(flatMapKey, flatMapValue);
}
}
@SuppressWarnings("unchecked")
private static void processList(String flatMapKey,
String flatMapValue,
List<Object> list) {
int dot = flatMapKey.indexOf('.');
int colon = flatMapKey.indexOf(':');
// nested map
if (dot > -1 && (dot < colon || colon == -1)) {
int index = Integer.parseInt(flatMapKey.substring(0, dot));
while (list.size() < index) {
list.add(null);
}
Object nestedMap = list.get(index - 1);
if (nestedMap == null) {
list.set(index - 1, new TreeMap<>());
}
nestedMap = list.get(index - 1);
processMap(flatMapKey.substring(dot + 1),
flatMapValue, (Map<String, Object>) nestedMap);
}
// nested list
else if (colon > -1 && (colon < dot || dot == -1)) {
int index = Integer.parseInt(flatMapKey.substring(0, colon));
while (list.size() < index) {
list.add(null);
}
Object nestedList = list.get(index - 1);
if (nestedList == null) {
list.set(index - 1, new ArrayList<>());
}
nestedList = list.get(index - 1);
processList(flatMapKey.substring(colon + 1),
flatMapValue, (List<Object>) nestedList);
}
// insert value
else if (dot == colon) {
int index = Integer.parseInt(flatMapKey);
while (list.size() < index) {
list.add(null);
}
list.set(index - 1, flatMapValue);
}
}
Flat map:
{1999.3:1=23, 1999.3:2=24, 1999.3:3=25, 1999.4:1=1, 1999.4:2=2, 1999.4:3.10=42,
2001.11.7:1=23, 2001.11.7:2=24, 2001.11.7:3=25,
2001.11.9:1=1, 2001.11.9:2=2, 2001.11.9:3=3, 2001.12=45}
Original tree:
{1999={3=[23, 24, 25], 4=[1, 2, {10=42}]},
2001={11={7=[23, 24, 25], 9=[1, 2, 3]}, 12=45}}