gpt4 book ai didi

Java 泛型 : method signature for (deep copy of) generic Maps

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:02:05 27 4
gpt4 key购买 nike

我有一些 Map,它们本身又可能包含 Map(任何类型)。我写了一个带有签名的方法:

public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);

但是,我现在想概括此代码以支持一般的 Map,但仍会返回与参数类型相同的对象。所以不是:

public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
public static <K,V> CheckedMap<K,V> deepCopyCheckedMap(CheckedMap<K,V> s);
public static <K,V> TreeMap<K,V> deepCopyTreeMap(TreeMap<K,V> s);
...
etc.

我想要这样的东西:

public static <K,V, M extends Map<K,V>> M<K,V> deepCopyMap(M<K,V> s);

但是,这给了我:

Multiple markers at this line
- The type M is not generic; it cannot be parameterized with arguments <K,
V>
- The type M is not generic; it cannot be parameterized with arguments <K,
V>

如何正确声明方法签名并仍然返回正确类型的对象(不在内部使用反射)?

对于这个项目,添加更多依赖项确实不是一个选项,所以我更喜欢不依赖外部库的解决方案。此外,我已经研究了 Cloneable 接口(interface),但是它只是一个标记接口(interface)(一般没有 Map 的实现)它对我没有多大用处.


编辑:作为引用,这是我用于深度复制嵌套 HashMap 的代码(代码工作正常):

public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> source){
HashMap<K,V> result = new HashMap<K, V>();
for(Map.Entry<K, V> entry : source.entrySet()){
K k = entry.getKey();
V v = entry.getValue();
if(k instanceof HashMap<?,?>){
k = (K) deepCopyHashMap((HashMap<?,?>) k);
}
if(v instanceof HashMap<?,?>){
v = (V) deepCopyHashMap((HashMap<?,?>) v);
}
result.put(k, v);
}
return result;
}

编辑:解决方案

  1. 这不是一个理想的解决方案。如果嵌套的 Map 的运行时类型没有默认构造函数,它将失败。我已经使用嵌套的 HashMap 对其进行了测试,运行时类型已正确复制。

    @SuppressWarnings("unchecked")
    public static <K,V, M extends Map<K,V>> M deepCopyMap(M source) throws InstantiationException, IllegalAccessException{
    M result = (M) source.getClass().newInstance();
    for(Map.Entry<K, V> entry : source.entrySet()){
    K k = entry.getKey();
    V v = entry.getValue();
    if(k instanceof Map<?,?>){
    k = (K) deepCopyMap((Map<?,?>) k);
    }
    if(v instanceof Map<?,?>){
    v = (V) deepCopyMap((Map<?,?>) v);
    }
    result.put(k, v);
    }
    return result;
    }
  2. 这样更安全,但需要明确列出所有已知类型:

    @SuppressWarnings("unchecked")
    public static <K,V, M extends Map<K,V>> M deepCopyMap(M source){
    M result;
    if(source instanceof HashMap){
    result = (M) new HashMap<K,V>();
    } else {
    //fail
    }
    // etc. add more types here
    for(Map.Entry<K, V> entry : source.entrySet()){
    K k = entry.getKey();
    V v = entry.getValue();
    if(k instanceof Map<?,?>){
    k = (K) deepCopyMap((Map<?,?>) k);
    }
    if(v instanceof Map<?,?>){
    v = (V) deepCopyMap((Map<?,?>) v);
    }
    result.put(k, v);
    }
    return result;
    }

最佳答案

泛型类型参数本身不能是泛型的。只需删除 M 的通用定义即可:

public static <K, V, M extends Map<K, V>> M deepCopyMap(M s);

通用定义M<K, V>你说的已经是隐含的,因为编译器必须确保 M extends Map<K, V>是真的。因此,定义 M<K, V>是多余的。

至于在方法内部创建一个副本会变得更加复杂。泛型类型提高了泛型方法用户的类型安全性。但是,在该方法内部,您就像使用采用原始 Map 的非泛型方法一样一无所知。作为它的论据。 (您当然可以进一步限制泛型类型。)

毕竟,我不会向您推荐您建议的方法。您建议您的 API 用户可以深度克隆任何类型的 Map这是作为方法的参数提供的。但是,你不能。 Map是一个公共(public)接口(interface),任何人都可以实现它。在运行时,您可能会被要求创建一个您不知道的深度克隆 map ,而您将无法做到。看看这个实现:

@SupressWarnings("unchecked")
public static <K, V, M extends Map<K, V>> M deepCopyMap(M s) {
Map map;
if(s.getClass() == HashMap.class) {
map = new HashMap();
} else if(s.getClass == LinkedHashMap.class) {
map = new LinkedHashMap();
} else {
throw new RuntimeException("unknown map type " + s.getClass());
}
for(Map.Entry<K, V> entry : source.entrySet()) {
K k = entry.getKey();
V v = entry.getValue();
if(k instanceof Map) {
map.put(k, deepCopyMap((Map) k));
} else {
result.put(k, v);
}
}
return (M) map;
}

这对用户来说不是很透明,如果 map 包含某些用户类型 map ,很可能会抛出异常。事实上,编译器会就此方法中的几乎所有内容向您发出警告,这是一个好兆头,表明这是一个坏主意。

相反,我实际上会推荐您只为已知类型提供深度克隆的重载方法。但是,如果您发现无法在运行时创建的嵌套映射,则必须抛出运行时异常。您正在寻找的那种类型安全很难实现。此外,我会将其作为契约(Contract)的隐含部分,即您不能使用嵌套 map ,其中 map 类型不在 Map 的指定组内。实现。

旁注:不限制 MV ,定义这些参数没有意义,因为您对这些参数一无所知。只需使用通配符 ? .

关于Java 泛型 : method signature for (deep copy of) generic Maps,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20330327/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com