如何获取Map的键和值类型

时间:2015-01-03 15:03:34

标签: java

我有这个代码,应用程序需要检查Map给定的密钥是否为String

    if(instance.getClass().equals(Map.class)){
        Map map = (Map) instance;
        if(keyIsString(map)){
           // do stuff with the map
           Iterator<Map.Entry> it = map.entrySet().iterator();
        }
    }

我可以通过使用迭代器获取第一个项目并按instanceof进行检查来实现,但这会导致我使用两个迭代器。获取Map键类型的最佳方法是什么?

更新:我创建了一个MapHelper类:

public class MapHelper {
    public static String getKeyType(Map map){
        String keyKind = Object.class.getName();
        Iterator<Map.Entry<Object,Object>> it = map.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<Object,Object> entry = it.next();
            Object entryKey = entry.getKey();
            keyKind = entryKey.getClass().getName();
        }
        return keyKind;
    }
    public static String getValueType(Map map){
        String valueKind = Object.class.getName();
        Iterator<Map.Entry<Object,Object>> it = map.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<Object,Object> entry = it.next();
            Object entryVal = entry.getValue();
            valueKind = entryVal.getClass().getName();
        }
        return valueKind;
    }
}

这还不错吗?

3 个答案:

答案 0 :(得分:4)

您无法在运行时确定地图的类型。由于类型删除,它们不再可用。

来自http://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure

  

在编译时检查泛型的类型正确性。通用的   然后在称为类型擦除的过程中删除类型信息。对于   例如,List<Integer>将转换为非泛型类型List,   通常包含任意对象。编译时检查   保证生成的代码是类型正确的。

     

在类型擦除之后,无法确定类型参数   运行。例如,在运行时检查ArrayList时   不是一般的方法来确定在类型擦除之前它是否是一个   ArrayList<Integer>ArrayList<Float>

如果您无法确保您的编译器已经正确检查了所有类型,那么您唯一的机会就是获取一个元素并假设所有其他元素来自同一类型。

答案 1 :(得分:2)

我不同意之前的评论。如果MapHelper类必须在未知的 Map 上测试它是通用的,则它不能设置通用映射参数。

如果您使用getValueType(Map)getKeyType(Map),则会返回地图中最后一个元素的类(键或值)。 我不认为你在寻找它。

public static boolean keyIsString(Map map) {
    boolean isString = !map.isEmpty();
    String keyKind = Object.class.getName();
    Iterator<Map.Entry> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry entry = it.next();
        Object entryKey = entry.getKey();
        if(!String.class.isInstance(entryKey)) {
            isString = false;
            break;
        }
    }
    return isString;
}

如果地图中的所有键都是字符串,则返回true,否则返回false或者地图为空。

答案 2 :(得分:0)

我在一个方法中完成了它,它返回 CSV (逗号分隔值)String中的KEY和VALUE类型名称,如“,”:

    public static String getMapKeyAndValueTypes(Map map) {
    StringBuilder sb = new StringBuilder();
    Iterator<Map.Entry> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry entry = it.next();
        sb.append(MapsUtils.getObjectInstanceOf(entry.getKey()))
            .append(',')
            .append(MapsUtils.getObjectInstanceOf(entry.getValue()));
        break;
    }
    return sb.toString();
}

调用方法:

Map<String, Integer> map1 = new HashMap<>();
map1.put("key1", 20); map1.put("key2", 30); map1.put("key3", 40);

String keyAndValueTypes = MapHelper.getMapKeyAndValueTypes(map1);
String entryKeyTypeName = keyAndValueTypes.substring(0, keyAndValueTypes.indexOf(","));
String entryValueTypeName = keyAndValueTypes.substring(keyAndValueTypes.indexOf(",") + 1);
System.out.println("Types Names: Key=" + entryKeyTypeName + " ; Value=" + entryValueTypeName);

输出是: Types Names: Key=String ; Value=Integer

在一种方法中,我们得到两者,并且可以选择使用其中一种或两种。