replace all keys in hashmap starting with a character
Set<String> tempSet = new HashSet<String>();
for (Map.Entry<String, String> entry : map.entrySet()) {
String orginalKeys = entry.getKey();
System.out.println(orginalKeys);
String newKey = orginalKeys.replace('.','/');
if (!newKey.equals(org开发者_开发百科inalKeys)) {
map.put(newKey, entry.getValue());
tempSet.add(orginalKeys);
map.remove(orginalKeys);
}
}
System.out.println(map);
This replaces only one key, but i want to replace all with the above occurrences. What is the wrong thing i am going with?
I see no problem with this code. Assuming, your map has more than one key that matches the critria, e.g. contains at least one dot (.
), more than one new keys should have been created with the values taken from the originalkeys and more than one of those originalkeys should have been deleted.
An alternative approach: simply create a new map and drop the old one:
Map<String, String> newMap = new HashMap<String, String>();
for (Map.Entry<String, String> entry : map.entrySet())
newMap.put(entry.getKey().replace('.', '/'), entry.getValue());
map = newMap;
(If you still need that tempSet
, modify the code inside the for loop)
This replaces only one key, but i want to replace all with the above occurrences. What is the wrong thing i am going with?
Normally I'd expect your code to give ConcurrentModificationException
. The problem is that you are modifying the map while you are iterating it.
The javadoc for HashMap
says this:
"The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a
ConcurrentModificationException
. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.""Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw
ConcurrentModificationException
on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs."
If you look at both my solution and @Colin Herbert's solution in the answers to your previous question, you will see that we carefully record what needs to be changed in separate data structures. Only when the iteration is complete do we make the changes to the original Map. This is critical. Without it the solutions don't work.
ideally this code should throw java.util.ConcurrentModificationException as you are iterating through the map.entrySet()) and at the same time updating the map.put(newKey, entry.getValue());
As indicated earlier, you could create a new temporary map and replace with original one
or you could get the keys in a list and iterate the list
String[] keyArray = map.keySet().toArray(new String[map.size()]);
Set<String> tempSet = new HashSet<String>();
for (String orginalKeys : keyArray) {
System.out.println(orginalKeys);
String newKey = orginalKeys.replace('.', '/');
if (!newKey.equals(orginalKeys)) {
map.put(newKey, map.get(orginalKeys));
tempSet.add(orginalKeys);
map.remove(orginalKeys);
}
}
System.out.println(map);
I'm not sure whether you can modify a map while iterating over it. Try collecting the entries to change in a list first, then later looping over that list to make the changes.
精彩评论