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);
}