I have several Map , which themselves can again contain Map (of any type). I wrote a method with a signature:
public static <K,V> HashMap<K,V> deepCopyHashMap(HashMap<K,V> s);
However, now I would like to generalize this code to support Map in general, but still return an object of the same type as the argument. Therefore, instead of:
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.
I would like something like this:
public static <K,V, M extends Map<K,V>> M<K,V> deepCopyMap(M<K,V> s);
However, this gives me:
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>
How to correctly declare a method signature and return an object of the correct type (without internal reflection)?
For this project, adding additional dependencies is really not an option, so I would prefer a solution that does not rely on external libraries. In addition, I looked at the Cloneable interface, but at the same time it was just a marker interface (without implementation for Map in general), this is not very useful for me.
Edit: For reference, this is my code for deep copying nested HashMap (code works correctly):
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; }
Edit: Solutions
This is not an ideal solution. It will fail if there is no default constructor for the environment type of the nested Map . I tested it with a nested HashMap , and the execution type is correctly copied.
@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; }
This is much safer, but all known types must be explicitly specified:
@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 {