将MultivaluedMap<String, String>转换为Map<String, List<String>>时遭遇PMD规则UseConcurrentHashMap报错的解决咨询
解决MultivaluedMap转Map时的PMD错误:UseConcurrentHashMap
咱们先拆解这个PMD错误的成因:
这条UseConcurrentHashMap规则是PMD在提醒你——如果你的代码运行在Java 5及以上环境,并且存在多线程并发访问这个Map的场景,普通的TreeMap(或者HashMap)在并发修改/读取时会有线程安全问题,比如抛出ConcurrentModificationException,或者出现数据不一致的情况。而ConcurrentHashMap是专门为并发场景设计的,它能在保证线程安全的同时,提供比同步包装类更好的性能。
不过这里要注意,你原代码用了TreeMap<String.CASE_INSENSITIVE_ORDER>来实现键的大小写不敏感排序,而ConcurrentHashMap本身是哈希表结构,不支持自定义排序,所以解决的时候得分情况处理:
情况一:你的代码确实存在并发访问场景
这里又分两种子情况:
- 不需要保持键的有序性,只需要大小写不敏感的键处理:
直接换成ConcurrentHashMap,同时保持将键转成小写的逻辑即可,这样既能满足并发安全,又能实现大小写不敏感的键匹配:public Map<String, List<String>> prepareParameters(MultivaluedMap<String, String> headers) { Map<String, List<String>> result = new ConcurrentHashMap<>(); headers.forEach((key, value) -> result.put(key.toLowerCase(), value)); return result; // 重点!原代码返回的是headers,这是个bug,必须改成返回result } - 既需要并发安全,又需要键按大小写不敏感排序:
可以用Collections.synchronizedSortedMap包装一个TreeMap,它能给有序的TreeMap加上线程安全的同步锁,不过性能上不如ConcurrentHashMap,适合有序需求优先级更高的场景:public Map<String, List<String>> prepareParameters(MultivaluedMap<String, String> headers) { Map<String, List<String>> result = Collections.synchronizedSortedMap( new TreeMap<>(String.CASE_INSENSITIVE_ORDER) ); headers.forEach((key, value) -> result.put(key.toLowerCase(), value)); return result; }
情况二:你的代码不存在并发访问场景
如果这个Map只会在单线程环境下使用,那这个PMD警告其实是没必要的,你可以选择:
- 直接忽略这个警告;
- 在方法上添加PMD的抑制注解,明确告诉工具你不需要这条规则检查:
@SuppressWarnings("PMD.UseConcurrentHashMap") public Map<String, List<String>> prepareParameters(MultivaluedMap<String, String> headers) { Map<String, List<String>> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); headers.forEach((key, value) -> result.put(key.toLowerCase(), value)); return result; // 同样要修正返回值的bug }
最后再敲个重点:你原代码最后返回的是headers而不是result,这等于你的转换逻辑完全没生效,一定要改成返回result!
内容的提问来源于stack exchange,提问作者Etiena
相关产品推荐
相关产品推荐

