Java自定义HashMap相等判断函数失效问题排查
自定义HashMap相等判断函数的问题分析
问题场景
尝试用自定义的matches函数判断两个HashMap是否相等,预期输出true,但实际输出false。以下是代码及运行结果:
代码片段
import java.util.HashMap; public class HashMapEquals{ private static boolean matches1(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ for(char c: one.keySet()){ if(one.get(c) != two.get(c)) return false; } return true; } private static boolean matches2(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ for(char c: two.keySet()){ if(two.get(c) != one.get(c)) return false; } return true; } private static boolean matches(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ boolean first = matches1(one, two); boolean second = matches2(one, two); System.out.println(first); System.out.println(second); return (first && second); } public static void main(String args[]){ HashMap<Character, Integer> one = new HashMap<>(); HashMap<Character, Integer> two = new HashMap<>(); one.put('a', 10000); two.put('a', 10000); matches(one, two); System.out.println(one.equals(two)); } }
运行输出
$ java HashMapEquals false false true
问题原因
核心问题出在用!=比较Integer对象:
Integer是引用类型,!=比较的是对象的内存地址(引用),而非实际数值。- 对于值在
-128~127范围内的Integer,Java会从常量池复用对象,此时!=能碰巧比较值相等;但当值超出这个范围时(比如代码中的10000),Java会创建新的Integer对象,此时两个值相同的Integer对象引用不同,!=返回true,导致matches1和matches2直接返回false。
而HashMap内置的equals()方法会正确遍历每个键值对,用equals()方法比较值的内容而非引用,所以能得到正确结果。
修复方案
把引用比较!=改成用equals()比较值内容,同时可以用Objects.equals()简化null值处理(避免空指针异常),还可以先判断两个HashMap的size是否相等,快速排除键数量不同的情况:
修复后的代码示例
import java.util.HashMap; import java.util.Objects; public class HashMapEquals{ private static boolean matches1(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ for(char c: one.keySet()){ if(!two.containsKey(c) || !Objects.equals(one.get(c), two.get(c))){ return false; } } return true; } private static boolean matches2(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ for(char c: two.keySet()){ if(!one.containsKey(c) || !Objects.equals(two.get(c), one.get(c))){ return false; } } return true; } private static boolean matches(HashMap<Character, Integer> one, HashMap<Character, Integer> two){ // 先判断size,快速排除不相等情况 if(one.size() != two.size()){ return false; } boolean first = matches1(one, two); boolean second = matches2(one, two); System.out.println(first); System.out.println(second); return (first && second); } public static void main(String args[]){ HashMap<Character, Integer> one = new HashMap<>(); HashMap<Character, Integer> two = new HashMap<>(); one.put('a', 10000); two.put('a', 10000); System.out.println(matches(one, two)); System.out.println(one.equals(two)); } }
内容的提问来源于stack exchange,提问作者Sai Pavan Kalyan Munaga
相关产品推荐
相关产品推荐

