It's a common bug that we try to use collection.remove during looping the collection.
For example: in ehcache 2.7.0 getAll method
This was fixed in latest version: ehcache 2.10.0 getAll method
Usually we use Iterator> it=map.entrySet().iterator(); then use it.remove() to delete the element.
Here the iterator of the map returned by compoundStore.getAll() may not support remove method.
That's why ehcache first adds all expired key to a HashSet, then call:
Here is the HashSet removeAll method:
public Map getAll(Collection keys) throws IllegalStateException, CacheException {
For example: in ehcache 2.7.0 getAll method
public Map
This was fixed in latest version: ehcache 2.10.0 getAll method
Usually we use Iterator
Here the iterator of the map returned by compoundStore.getAll() may not support remove method.
That's why ehcache first adds all expired key to a HashSet, then call:
try { elements.keySet().removeAll(expired); } catch (UnsupportedOperationException e) { elements = new HashMap(elements); elements.keySet().removeAll(expired); }
Here is the HashSet removeAll method:
* Note that this implementation will throw an
* UnsupportedOperationExceptionif the iterator returned by the
* iteratormethod does not implement the removemethod.
public boolean removeAll(Collection c) {
Objects.requireNonNull(c);
boolean modified = false;
if (size() > c.size()) { // optimization: different branch based on size diff
for (Iterator i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
ehcache 2.10.0 getAll methodpublic Map
getAllObserver.begin(); checkStatus(); if (disabled) { return null; } if (keys.isEmpty()) { getAllObserver.end(GetAllOutcome.ALL_HIT, 0, 0); return Collections.EMPTY_MAP; } Mapelements = compoundStore.getAll(keys); Set expired = new HashSet (); for (Entry entry : elements.entrySet()) { Object key = entry.getKey(); Element element = entry.getValue(); if (element != null) { if (isExpired(element)) { tryRemoveImmediately(key, true); expired.add(key); } else { element.updateAccessStatistics(); } } } if (!expired.isEmpty()) { try { elements.keySet().removeAll(expired); } catch (UnsupportedOperationException e) { elements = new HashMap(elements); elements.keySet().removeAll(expired); } } int requests = keys.size(); int hits = elements.size(); if (hits == 0) { getAllObserver.end(GetAllOutcome.ALL_MISS, 0, requests); } else if (requests == hits) { getAllObserver.end(GetAllOutcome.ALL_HIT, requests, 0); } else { getAllObserver.end(GetAllOutcome.PARTIAL, hits, requests - hits); } return elements; }