{"record":{"id":"362fd4d6cfb707c6","repo":"chinabugotech/hutool","slug":"cache-values-iterator-is-not-support-to-modify","errorCode":null,"errorMessage":"Cache values Iterator is not support to modify.","messagePattern":"Cache values Iterator is not support to modify\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObjIterator.java","lineNumber":58,"sourceCode":"\t/**\n\t * @return 下一个值\n\t */\n\t@Override\n\tpublic CacheObj<K, V> next() {\n\t\tif (false == hasNext()) {\n\t\t\tthrow new NoSuchElementException();\n\t\t}\n\t\tfinal CacheObj<K, V> cachedObject = nextValue;\n\t\tnextValue();\n\t\treturn cachedObject;\n\t}\n\n\t/**\n\t * 从缓存中移除没有过期的当前值，此方法不支持\n\t */\n\t@Override\n\tpublic void remove() {\n\t\tthrow new UnsupportedOperationException(\"Cache values Iterator is not support to modify.\");\n\t}\n\n\t/**\n\t * 下一个值，当不存在则下一个值为null\n\t */\n\tprivate void nextValue() {\n\t\twhile (iterator.hasNext()) {\n\t\t\tnextValue = iterator.next();\n\t\t\tif (nextValue.isExpired() == false) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tnextValue = null;\n\t}\n}\n","sourceCodeStart":40,"sourceCodeEnd":74,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObjIterator.java#L40-L74","documentation":"CacheObjIterator.remove() is intentionally unimplemented — the underlying cache does not support removing entries through its value iterator, so it throws UnsupportedOperationException. Hutool's cache iterator is read-only by design; mutation must go through the cache's own remove/evict API. Calling remove() on either the entry iterator or the value iterator derived from a CacheImpl will hit this.","triggerScenarios":"Obtaining an iterator via cache.iterator(), cacheCacheObj.values().iterator(), or similar, then calling .remove() on it (often from enhanced-for loops that use Iterator.remove, or copy-by-filter utilities that mutate during iteration).","commonSituations":"Using Java streams/loops that expect a mutable iterator; writing a filter-and-prune routine against the cache directly instead of the cache API; porting code from a Map-based implementation.","solutions":["Do not call remove() on the iterator; collect keys and remove them via Cache.remove(key) after iteration.","Use cache.clear() or cache.prune() to evict rather than iterator mutation.","If building a derived collection, copy entries into a new Map/List first, then mutate that."],"exampleFix":"// before\nIterator<CacheObj<K,V>> it = cache.iterator();\nwhile (it.hasNext()) { if (stale(it.next())) it.remove(); }\n// after\nList<K> toRemove = new ArrayList<>();\ncache.forEach(it2 -> { if (stale(it2)) toRemove.add(it2.getKey()); });\ntoRemove.forEach(cache::remove);","handlingStrategy":"validation","validationCode":"// never call iterator.remove() on a cache iterator; collect keys first\nList<K> keys = new ArrayList<>();\ncache.iterator().forEachRemaining(o -> { if (stale(o)) keys.add(o.getKey()); });\nkeys.forEach(cache::remove);","typeGuard":null,"tryCatchPattern":"try { it.remove(); } catch (UnsupportedOperationException e) { /* use cache.remove(key) instead */ }","preventionTips":["Treat all hutool cache iterators as read-only.","Prefer cache.remove(key) / cache.prune() for eviction."],"tags":["cache","iterator","unsupported-operation"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}