I've run into an oddity with Sets that reference a Maps keySet. It appears you can remove a value from that Set and it will remove the record from the corresponding Map. Yet if you try and add anything to the same set if results in an Exception:
System.FinalException: Collection is read-only
So calls to
Set.remove(x); are allowed and
Set.add(x); throw exceptions.
It makes sense that I shouldn't be allowed to add anything to the Set as the Map wouldn't then have a corresponding value.
But why allow the remove operation on an otherwise read only collection? It seems like an easy way to inadvertently change the Map when you are only dealing with a Set.
I encountered this when using a Set derived from the getPopulatedFieldsAsMap() Map. It seems like the safest option here is to clone the resulting Set before returning it to other code.
Map<Id, Account> accountsMap = new Map<Id, Account>([Select Id from Account limit 10]); Set<Id> accountIds = accountsMap.keySet(); Id testAccountId = accountsMap.values().Id; System.assert(accountsMap.containsKey(testAccountId)); System.assert(accountIds.contains(testAccountId)); accountIds.remove(testAccountId); System.assert(!accountIds.contains(testAccountId)); // Fails as removal from the Set also removes from the Map //System.assert(accountsMap.containsKey(testAccountId)); // Throws System.FinalException: Collection is read-only accountIds.add(testAccountId);