调用Map的keySet.removeAll方法抛出UnsupportedOperationException问题咨询
异常原因分析
- 首先要明确:参数的
final修饰和对象本身是否支持修改是完全无关的两个概念。final修饰方法参数仅限制你无法在方法内部将searchDocumentResults这个变量重新指向另一个Map实例,不会对该变量指向的Map对象本身的读写权限产生任何影响。 - 你遇到的异常本质是:传入的
searchDocumentResults本身就是不可变Map实例,这类Map的所有修改操作(包括remove、put、keySet().removeAll()等)默认都会抛出UnsupportedOperationException。 - 不可变Map的常见生成场景:
- 上游调用方使用
Collections.unmodifiableMap()对原始可修改Map做了包装后传给你的方法 - 上游使用Java9+的
Map.of()、Map.ofEntries()等工厂方法直接生成不可变Map实例 - 部分第三方框架返回的查询结果默认是不可变的,避免下游误改
- 上游调用方使用
修复方案
推荐优先选择不修改入参的方案,避免对上游逻辑产生副作用,实现如下:
private Map<String, String> getSearchResultsWithoutOverUsedData( Map<String, String> searchDocumentResults ) { // 将不可变入参拷贝为可修改的HashMap实例 Map<String, String> modifiableResults = new HashMap<>(searchDocumentResults); List<String> overUsedTestData = this.extractOverUsedTestData(modifiableResults); if (!overUsedTestData.isEmpty()) { this.deleteSearchResultsAboveThresholdUsage(overUsedTestData); modifiableResults.keySet().removeAll(overUsedTestData); } return modifiableResults; }
如果你确认可以要求上游传入可修改的Map,也可以调整上游逻辑,传入HashMap、ConcurrentHashMap等原生支持修改的Map实现,无需修改当前方法逻辑。
内容的提问来源于stack exchange,提问作者AnOldSoul
相关产品推荐
相关产品推荐

