How to clear out the contents of a map when clear() method call throws UnsupportedOperationException?

二次信任 提交于 2019-12-24 01:00:00

问题


How can I empty a map contents if I keep getting an UnsupportedOperationException when I call clear() method on the map instance ?


回答1:


You shouldn't. There is something wrong in the contracts of the collaborating objects and their methods. You expect a modifiable map, but get an unmodifiable view. You should redefine the contracts and/or adopt any of the implementations accordingly. If you are not in control of the one, who is passing you that map, then there is probably a reason for it passing you an unmodifiable view.




回答2:


If the Map is an UnmodifiableMap (for instance, gotten from Collections.unmodifiableMap()), there's little you can (and should) do to modify it, except creating a new reference and clearing it.

Map unmodifiable = Collections.unmodifiableMap(m);
Map newMap = new HashMap(unmodifiable);
newMap.clear();
unmodifiable = newMap;

That said, it is actually possible to modify an UnmodifiableMap. It turns out that Collections.UnmodifiableMap is nothing more than a class implementing the Map interface, and wrapping the actual Map. It delegates on the wrapped Map for its read-only methods, and throws UnsupportedOperationExceptions in its implementations of methods that alter the map. It is possible to get the wrapped Map by reflection, and therefore modify it.

DISCLAIMER: Take into account that this must be used with extreme caution. If the unmodifiable map is provided by a a library or similar, it might be making assumptions about its nature, and violateing its contract can lead to unexpected/undesirable results. Also, this might be relying on internals that might be changed without notice or differ between versions.

// Creates a standard map
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("1", "a");
myMap.put("2", "b");
// Creates an unmodifiableMap. Actually a wrapper for myMap.
Map unmodifiableMap = Collections.unmodifiableMap(myMap);
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());
try{
    // Get classes declared in java.util.Collections
    Class[] classes = Collections.class.getDeclaredClasses();
    for(Class cl : classes) {
        // Look for the UnmodifiableMap class
        if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
            // The wrapped Map is in an attribute called "m"
            Field field = cl.getDeclaredField("m");
            field.setAccessible(true);
            // Get the wrapped map
            Object obj = field.get(unmodifiableMap);
            Map map = (Map) obj;
            // modify it
            map.clear();
        }
    }
}
catch (Exception e){ System.out.println(); }
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());

(credit to this blog post)



来源:https://stackoverflow.com/questions/14772132/how-to-clear-out-the-contents-of-a-map-when-clear-method-call-throws-unsupport

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!