Java中地图内的分解列表
我想分解地图中的列表,并将地图转换为地图列表 例如: 我想将下面的地图转换为Java中地图内的分解列表,java,java-8,Java,Java 8,我想分解地图中的列表,并将地图转换为地图列表 例如: 我想将下面的地图转换为map 到 如下所示的地图列表(即List) 在Java 8中最好的方法是什么? 到目前为止,我试着如下。但我知道这不是最好的办法 package com.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Maptest {
map
到
如下所示的地图列表(即List
)
在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);
}
}
package.com.test;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
公共类映射测试{
公共静态void main(字符串[]args){
Map Map=newhashmap();
列表=新的ArrayList();
List listofmap=new ArrayList();
列表。添加(“abc”);
列表。添加(“xyz”);
地图放置(“键1”、“消息1”);
map.put(“键2”、“消息2”);
地图放置(“键3”,列表);
系统输出打印项次(map);
list1=(ArrayList)map.get(“key3”);
for(字符串s:list1){
Map localMap=newhashmap();
localMap.put(“key1”,(String)map.get(“key1”);
localMap.put(“key2”,(String)map.get(“key2”);
localMap.put(“键3”,s);
添加(localMap);
}
System.out.println(列表地图);
}
}
在给出解决方案之前,我必须警告您:您应该考虑您的数据结构,并且应该避免在生产代码中使用此解决方案。这是非常糟糕的数据结构设计
也就是说,解决方案如下:
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;
}
私有流密钥列表(映射){
//检索映射到列表值的所有键
返回map.keySet().stream()
.filter(key->List.class.isAssignableFrom(map.get(key.getClass()));
}
专用布尔类型检查(映射){
//检查是否只有一个列表值
//所有其他值都是字符串
返回KeysforList(map).count()==1
&&map.values().stream().map(o->o.getClass())
.filter(t->t.equals(String.class)).count()==map.size()-1;
}
公共列表分解(地图){
如果(!类型检查(地图)){
抛出新的ClassCastException(
“映射值没有所需的类型:一个列表加任意多个字符串”);
}
最终字符串listKey=keysForLists(map.findFirst().get();
最终列表listValue=(List)map.get(listKey);
最终列表结果=新建ArrayList();
//为每个列表值创建一个新映射
listValue.forEach(值->{
final Map m=新的HashMap();
//将列表值添加到映射中
m、 put(listKey,value);
//将所有其他键/值对添加到映射中
map.keySet().stream().filter(k->!k.equals(listKey))
.forEach(k->m.put(k,(String)map.get(k));
结果:添加(m);
});
返回结果;
}
//将val映射到列表
Map tempMap=Map.entrySet(),
e->(e-instanceof-ArrayList)?(List)e:(List)Arrays.asList(e.toString());
//抓住马克斯
int max=tempMap.values().stream().mapToInt(e->e.size()).max().orElse(0);
//创造结果
最终列表结果=新建ArrayList();
对于(int i=0;i我们需要更多信息。例如,如果有两个条目,每个条目都有一个列表,会发生什么?叉积?这确实会很快爆炸。@UniversE是的。我只需要一种叉积。输出列表大小应该等于输入映射中列表中的项数。对于正好为3的映射,此代码是可以的映射项。但是,如果您要处理任意数量的映射项,并且可能有多个列表,那么它甚至不会关闭。还要注意,HashMap没有任何定义的迭代顺序,而列表有。@PadmanabhanVijendran“恰好有一个列表”part使它变得简单多了。但是您的数据结构很混乱。难道没有更好的设计机会吗?无论如何,我目前正在准备一个解决方案。如果(!typecheck(map))…
:)那么,您已经大大简化了这一点……忘记了:result.add(m);而且你忘了什么是y
。为它创建一个合适的函数怎么样?
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);
}
}
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;
}
// 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);
}