我想爆炸地图中的列表并将地图转换为地图列表。
例如:
我想以Map<String, Object>
{key1=message1, key2=message2, key3=[abc, xyz]}
到
以下地图列表(即List<Map<String,String>>
)
[{key1=message1, key2=message2, key3=abc},{key1=message1, key2=message2, key3=xyz}]
最好的方法是什么,最好是在Java 8中?
到目前为止,我尝试过如下。但我知道这不是最好的方法。
package com.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Maptest {
public static void main(String[] args){
Map<String,Object> map = new HashMap<>();
List<String> list = new ArrayList<>();
List<Map<String,String>> listofMaps = new ArrayList<>();
list.add("abc");
list.add("xyz");
map.put("key1","message1");
map.put("key2","message2");
map.put("key3",list);
System.out.println(map);
List<String> list1 = (ArrayList)map.get("key3");
for(String s: list1){
Map<String,String> localMap = new HashMap<>();
localMap.put("key1",(String)map.get("key1"));
localMap.put("key2",(String)map.get("key2"));
localMap.put("key3",s);
listofMaps.add(localMap);
}
System.out.println(listofMaps);
}
}
答案 0 :(得分:1)
在给您解决方案之前,我必须提醒您:您应该考虑一下您的数据结构,应该避免在生产代码中使用此解决方案。这是非常糟糕的数据结构设计。
那就是说,这是解决方案:
private Stream<String> keysForLists(Map<String, Object> map) {
// retrieve all keys which map to list values
return map.keySet().stream()
.filter(key -> List.class.isAssignableFrom(map.get(key).getClass()));
}
private boolean typecheck(Map<String, Object> map) {
// check if there is really just one list value
// and all the other values are strings
return keysForLists(map).count() == 1
&& map.values().stream().map(o -> o.getClass())
.filter(t -> t.equals(String.class)).count() == map.size() - 1;
}
public List<Map<String, String>> explode(Map<String, Object> map) {
if (!typecheck(map)) {
throw new ClassCastException(
"Map values do not have the required types: one list plus arbitrarily many strings");
}
final String listKey = keysForLists(map).findFirst().get();
final List<String> listValue = (List<String>)map.get(listKey);
final List<Map<String, String>> result = new ArrayList<>();
// for each list value create a new map
listValue.forEach(value -> {
final Map<String, String> m = new HashMap<>();
// add the list value to the map
m.put(listKey, value);
// add all the other key/value pairs to the map
map.keySet().stream().filter(k -> !k.equals(listKey))
.forEach(k -> m.put(k, (String)map.get(k)));
result.add(m);
});
return result;
}
答案 1 :(得分:1)
// map val to List<String>
Map<String, List<String>> tempMap = map.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
e -> (e instanceof ArrayList) ? (List<String>) e : (List<String>) Arrays.asList(e.toString())));
// get max
int max = tempMap.values().stream().mapToInt(e -> e.size()).max().orElse(0);
// create result
final List<Map<String, String>> result = new ArrayList<>();
for (int i = 0; i <= max; i++) {
final Map<String, String> m = new HashMap<>();
for (String key : map.keySet()) {
String val = Optional.of(tempMap.get(key).get(i)).orElse(tempMap.get(key).get(i - 1));
m.put(key, val);
}
result.add(m);
}