问题
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