如何获取映射的键和值类型



我有这段代码,应用程序需要做一些检查,检查给定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进行检查来做到这一点,但这会导致我使用两个迭代器。获取地图键类型的最佳方法是什么?

更新:我创建了一个地图助手类:

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

这够好吗?

您无法在运行时确定映射的类型。由于类型擦除,它们不再可用。

从 http://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure

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

由于

类型擦除,无法在 运行时。例如,当在运行时检查 ArrayList 时,有 不是确定在类型擦除之前是否是 ArrayList<Integer>ArrayList<Float>.

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

我不同意之前的评论。如果 MapHelper 类必须在未知 Map 上测试它才能成为泛型类,则不得设置泛型 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;
}

如果映射中的所有键都是 String,这将返回 true,否则false或映射为空。

我用一种方法做到了,该方法以 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

在一种方法中,我们得到了两者,可以选择使用一种或另一种或两者兼而有之。

最新更新