Map的containsKey遇到的问题

本文探讨了在Java中使用HashMap时,不同类型的键(Integer与Long)导致containsKey方法返回错误的问题。通过分析源码,揭示了hashCode一致但equals方法失败的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在coding的过程遇到一个问题:

public class HashMapDemo {
    public static void main(String[] args) {
        testGo();
    }

    public static void testGo() {
        Map<Long, String> badGodMap = new HashMap<>();
        badGodMap.put(23L, "jack");
        badGodMap.put(24L, "tom");

        Integer oneKey = 23;
        // oneKey是Integer类型的 
        System.out.println("integer: " + badGodMap.containsKey(oneKey));   // false 

        Long longKey = 23L;
        // longKey是Long型的 
        System.out.println("long: " + badGodMap.containsKey(longKey)); // true 
    }
}

看了containsKey的源码是要去比较对象的hashCode的以及进行equals判断,让我输出其中的hashCode一探究竟:

public static void testGo() {
        Map<Long, String> badGodMap = new HashMap<>();
        badGodMap.put(23L, "jack");
        badGodMap.put(24L, "tom");

        Integer oneKey = 23;
        Long longKey = 23L;

        System.out.println("integer hashcode: " + getHashCode(oneKey));   // 23
        System.out.println("long hashcode: " + getHashCode(longKey));   // 23

    }

    public static int getHashCode(Object key) {
        return key.hashCode();
    }

获取的hashcode都是一样的,
那就是在比较equals的时候出问题了,看Integer的equals源码:

  public boolean equals(Object obj) {
        if (obj instanceof Integer) { //focus here 
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

看到这里就明白了,类型不一样,进行equals比较肯定会失败:

   Integer oneKey = 23;
   Long longKey = 23L;
   System.out.println(oneKey.equals(longKey)); // false 
/** * 验证单个Map中是否包含有效的signDate * @param map 待检查的Map * @return true表示有效,false无效 */ private boolean isValidSignDate(Map<String, Object> map) { if (map == null) { return false; } if (!map.containsKey("signDate")) { return false; } Object value = map.get("signDate"); if (value == null) { return false; } if (value instanceof String) { // 字符串类型,去除首尾空格后检查是否为空 return !((String) value).trim().isEmpty(); } else { return false; } } /** * 验证单个Map中是否包含有效的contractNum * @param map 待检查的Map * @return true表示有效,false无效 */ private boolean isValidContractNum(Map<String, Object> map) { if (map == null) { return false; } if (!map.containsKey("contractNum")) { return false; } Object value = map.get("contractNum"); if (value == null) { return false; } if (value instanceof String) { // 字符串类型,去除首尾空格后检查是否为空 return !((String) value).trim().isEmpty(); } else { return false; } } /** * 验证单个Map中是否包含有效的itemName * @param map 待检查的Map * @return true表示有效,false无效 */ private boolean isValidItemName(Map<String, Object> map) { if (map == null) { return false; } if (!map.containsKey("itemName")) { return false; } Object value = map.get("itemName"); if (value == null) { return false; } if (value instanceof String) { // 字符串类型,去除首尾空格后检查是否为空 return !((String) value).trim().isEmpty(); } else { return false; } } /** * 验证单个Map中是否包含有效的itemName * @param map 待检查的Map * @return true表示有效,false无效 */ private boolean isValidAmount(Map<String, Object> map) { if (map == null) { return false; } if (!map.containsKey("amount")) { return false; } Object value = map.get("amount"); if (value == null) { return false; } if (value instanceof String) { // 字符串类型,去除首尾空格后检查是否为空 return !((String) value).trim().isEmpty(); } else { return false; } }四个方法合成一个方法
最新发布
07-27
### Java `containsKey` 方法详解 #### 一、概述 在Java编程语言中,`containsKey()` 是用于检查映射(Map)结构内是否存在特定键的方法。此方法广泛应用于多种实现类之中,如HashMap、Hashtable以及专门处理枚举类型的EnumMap等。 对于不同容器而言,该函数的具体行为保持一致——即传入一个对象作为参数并判断其是否存在于当前集合所维护的键集当中;如果存在则返回布尔值`true`表示确认找到对应关系,反之亦然[^1]。 #### 二、具体应用案例分析 ##### (一)常规Map接口下的运用场景 当操作基于哈希表原理构建的数据存储器时(例如HashMap),可以通过调用`containsKey()`快速定位目标记录的位置而不必遍历整个列表: ```java import java.util.HashMap; public class Main { public static void main(String[] args){ HashMap<Integer, String> students = new HashMap<>(); // 添加学生信息到map中 students.put(1,"Alice"); students.put(2,"Bob"); int idToCheck = 1; System.out.println("Checking student with ID "+idToCheck+": " +(students.containsKey(idToCheck)? "Exists":"Not Found")); } } ``` 上述代码展示了如何利用`containsKey()`来验证某个学号是否已被注册过[^4]。 ##### (二)针对特殊化类型—EnumMap的操作方式 由于EnumMap仅接受预定义好的枚举常量作为有效索引项,因此在此基础上执行相同逻辑显得更为直观简洁: ```java enum Weekday { MONDAY,TUESDAY,WEDNESDAY } public class TestEnumMapContainsKey { private final EnumMap<Weekday, Integer> weekDayCounters = new EnumMap<>(Weekday.class); public boolean checkIfPresent(Weekday dayOfWeek){ return this.weekDayCounters.containsKey(dayOfWeek); } public static void main(String []args){ var tester=new TestEnumMapContainsKey(); // 初始化计数器... tester.checkIfPresent(Weekday.MONDAY); } } ``` 这里通过创建了一个名为`weekDayCounters` 的EnumMap实例,并借助于`checkIfPresent()` 函数实现了对给定工作日名称的有效性校验过程[^2]。 ##### (三)Properties 类中的表现形式 值得注意的是,在某些情况下开发者可能会遇到另一种特殊的关联数组变体 — Properties 。它本质上也是继承自 Hashtable ,所以同样支持类似的查询机制 : ```java import java.util.Properties; class PropertyExample{ public static void main (String arg[]){ Properties prop =new Properties (); // 设置属性值 prop.setProperty ("name","John Doe"); prop.setProperty ("age", "30"); String key="name"; System.out.printf("Property '%s' %sexist.\n", key, prop.containsKey(key)?"does ":"doesn't "); } } ``` 这段程序片段很好地诠释了怎样在一个配置文件解析过程中运用`containsKey()` 来确保所需设置项确实可用[^3]。 #### 总结 综上所述,无论是在标准库提供的通用型数据结构还是更专业的领域模型里,“containsKey” 都扮演着不可或缺的角色。理解这一概念有助于提高编码效率的同时也增强了应用程序本身的健壮性和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值