Java判断HashMap所有key是否存在于ArrayList的更优实现方案
优化方案说明
你当前的实现可以正常完成校验逻辑,但存在两处明显的可优化点:
- 固定的合法key集合写在方法内部,每次调用方法都会重复创建相同内容的ArrayList,产生无意义的内存开销
- 基于ArrayList做存在性判断时,
contains()方法需要从头遍历列表匹配元素,时间复杂度为O(n),如果合法key数量多、传入Map的key数量也大,整体校验的时间复杂度会达到O(m*n),性能表现差。
推荐实现:基于HashSet做校验(性能最优,兼容性好)
核心优化点是把固定的合法key提前存为全局复用的HashSet常量,HashSet基于哈希表实现,contains()判断的时间复杂度是O(1),整体校验的时间复杂度可以降到O(m)(m为传入Map的key数量),同时避免重复创建集合对象。
// 类加载时就初始化合法key集合,全局复用,禁止修改 private static final Set<String> VALID_KEYS = Collections.unmodifiableSet( new HashSet<>(Arrays.asList("One", "Two", "Three")) ); public boolean check(Map<String, String> map) { // 遍历Map的所有key,只要有一个不在合法集合中就直接返回false for (String key : map.keySet()) { if (!VALID_KEYS.contains(key)) { return false; } } return true; }
如果追求代码简洁,也可以直接调用Set的containsAll方法,逻辑完全等价:
private static final Set<String> VALID_KEYS = Collections.unmodifiableSet( new HashSet<>(Arrays.asList("One", "Two", "Three")) ); public boolean check(Map<String, String> map) { return VALID_KEYS.containsAll(map.keySet()); }
Java 8+ 流式写法
如果你的项目使用Java 8及以上版本,可以用Stream API实现,逻辑更直观,同样支持短路匹配(遇到非法key会立刻终止遍历,不用遍历完所有元素):
private static final Set<String> VALID_KEYS = Collections.unmodifiableSet( new HashSet<>(Arrays.asList("One", "Two", "Three")) ); public boolean check(Map<String, String> map) { return map.keySet().stream().allMatch(VALID_KEYS::contains); }
补充说明
如果你的合法key数量一直保持个位数的规模,ArrayList和HashSet的性能差异几乎感知不到,但用HashSet做存在性判断是通用的最佳实践,可以避免后续业务迭代、合法key数量上涨后出现性能问题。
内容的提问来源于stack exchange,提问作者Ramachandran Rajasekaran
相关产品推荐
相关产品推荐

