Map使用对象作key

Map使用对象作key

Map介绍:

Map是一个集合,一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是整数。在Map中键(key)可以是任意类型的对象。Map中不能有重复的键(Key),每个键(key)都有一个对应的值(value);

Map的key和value都是泛型的,所以Map的key和value可以任意类型的

(泛型讲解:https://wenku.baidu.com/view/511465055a0102020740be1e650e52ea5518ceae.html

hashCode方法详解(https://wenku.baidu.com/view/f0e3903e13a6f524ccbff121dd36a32d7375c761.html

使用对象做Map的key会出现那些问题:

不重写HashCode方法和equals方法时:

内容相等的对象创建多次,分别调用hashCode方法获取的哈希值都是不相等的,所以HashMap中会出现相同的key对象存在;解决这个的办法对象重写HashCode方法和equals方法,使用指定的哈希算法和equals方法这样可以避免上述情况;

重写HashCode方法和equals方法出现时:

当修改已经存放在HashMap中的对象时,HashMap中key也会同步修改,但是这个key所在的哈希值还是之前的哈希值所在的位置,这样会出现,使用修改前的key查value,查到所在的位置但是调用equals方法两个key值不相等结果查不到值,使用新的key去找,会通过新的key对象的哈希值去找,两个哈希值不相等,也查不到之前的value值了,这个值永远也查不到了;

实验key对象的案例:

/**
 * 创建用户对象
 */
class User implements Serializable {

    /**
     * 姓名
     */
    public String name;
    /**
     * 身份证号
     */
    public String idCard;
    /**
     *班级
     */
    public String clazz;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public static void main(String[] args) {
        //创建用户对象做key的HashMap集合
        HashMap<User, String> map = new HashMap<>();
        /**
         * 创建小明用户对象
         * 存放到map中
         */
        User xiaoMing = new User();
        xiaoMing.setName("小明");
        xiaoMing.setIdCard("4243124");
        xiaoMing.setClazz("二班小明");
        map.put(xiaoMing,"xiaoMing");
        System.out.println("xiaoMing的哈希值:"+xiaoMing.hashCode());

        /**
         * 在重新新建小明对象
         * 存放到map中
         */
        User xiaoMing2 = new User();
        xiaoMing2.setName("小明");
        xiaoMing2.setIdCard("4243124");
        xiaoMing2.setClazz("二班小明");
        map.put(xiaoMing2,"xiaoMing2");
        System.out.println("xiaoMing2的哈希值:"+xiaoMing2.hashCode());
        for (User user : map.keySet()) {
            System.out.println(map.get(user));
        }

    }

}

运行结果(控制台输出了两个小明对象):
在这里插入图片描述

原因HashMap是通过key的哈希值去放的元素的

HashMap putget方法源码解析文章(https://wenku.baidu.com/view/b9865541f6335a8102d276a20029bd64783e6281.html )

在这里插入图片描述

解决上述问题方式:

用户实体类中重写equals方法和hashCode方法或者使用Lombok中的@EqualsAndHashCode注解;

/**
 * 创建用户对象
 */
//@EqualsAndHashCode
class User implements Serializable {

    /**
     * 姓名
     */
    public String name;
    /**
     * 身份证号
     */
    public String idCard;
    /**
     *班级
     */
    public String clazz;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return name.equals(user.name) && idCard.equals(user.idCard) && clazz.equals(user.clazz);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, idCard, clazz);
    }

    /**
     * main方法测试
     * @param args
     */
    public static void main(String[] args) {
        //创建用户对象做key的HashMap集合
        HashMap<User, String> map = new HashMap<>();
        /**
         * 创建小明用户对象
         * 存放到map中
         */
        User xiaoMing = new User();
        xiaoMing.setName("小明");
        xiaoMing.setIdCard("4243124");
        xiaoMing.setClazz("二班小明");
        map.put(xiaoMing,"xiaoMing");
        System.out.println("xiaoMing的哈希值:"+xiaoMing.hashCode());

        /**
         * 在重新新建小明对象
         * 存放到map中
         */
        User xiaoMing2 = new User();
        xiaoMing2.setName("小明");
        xiaoMing2.setIdCard("4243124");
        xiaoMing2.setClazz("二班小明");
        map.put(xiaoMing2,"xiaoMing2");
        System.out.println("xiaoMing2的哈希值:"+xiaoMing2.hashCode());
        for (User user : map.keySet()) {
            System.out.println(map.get(user));
        }

    }

}

重写之后的结果(map中只有一个元素了):
在这里插入图片描述

重写之后有出现新的问题:

再次修改map中key的对象之后将永久获取不到之前的值了;

如果再次保存的话也不会覆盖之前的元素只会新增一个元素如下实验;

/**
 * 创建用户对象
 */
class User implements Serializable {

    /**
     * 姓名
     */
    public String name;
    /**
     * 身份证号
     */
    public String idCard;
    /**
     *班级
     */
    public String clazz;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return name.equals(user.name) && idCard.equals(user.idCard) && clazz.equals(user.clazz);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, idCard, clazz);
    }

    /**
     * main方法测试
     * @param args
     */
    public static void main(String[] args) {
        //创建用户对象做key的HashMap集合
        HashMap<User, String> map = new HashMap<>();
        /**
         * 创建小明用户对象
         * 存放到map中
         */
        User xiaoMing = new User();
        xiaoMing.setName("小明");
        xiaoMing.setIdCard("4243124");
        xiaoMing.setClazz("二班小明");
        map.put(xiaoMing,"xiaoMing");
        System.out.println("xiaoMing的哈希值:"+xiaoMing.hashCode());
        xiaoMing.setClazz("三班小明");
        map.put(xiaoMing,"三班小明");
        System.out.println("三班xiaoMing的哈希值:"+xiaoMing.hashCode());
        map.get(xiaoMing);

        /**
         * 在重新新建小明对象
         * 存放到map中
         */
        User xiaoMing2 = new User();
        xiaoMing2.setName("小明");
        xiaoMing2.setIdCard("4243124");
        xiaoMing2.setClazz("二班小明");
        map.put(xiaoMing2,"xiaoMing2");
        System.out.println("xiaoMing2的哈希值:"+xiaoMing2.hashCode());
        for (User user : map.keySet()) {
            System.out.println(map.get(user));
        }

    }

}

运行数据时
在这里插入图片描述

结果如下:

在这里插入图片描述

原因是因为修改了key对象之后同步修改了之前的key但是map存储时使用key是之前的key存放的元素 所以就找不到之前的元素了

而且使用keySet循环查也找不到之前的数据了 就是因为使用新key的哈希值和之前的不一样造成的

& 号详细讲解:https://blog.csdn.net/IT_dog/article/details/123212486

在这里插入图片描述

结语

谢谢观看,如有疑问欢迎留言,上面的验证和解析可能有错误之处,欢迎留言指导。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
std::map是C++标准库中的一个关联容器,它将一对键值(key-value)存在一个有序的集合中。默认情况下,std::map使用std::less来对key进行升序排列,可以使用std::greater来对key进行降序排序。 举个例子,如果我们创建一个std::map对象t,并插入一些键值对,如t.insert(std::make_pair(1, "a")); t.insert(std::make_pair(2, "b")); t.insert(std::make_pair(3, "c")); t.insert(std::make_pair(4, "d"));,那么t中的键值对的顺序将按照key的升序排序,即{1: "a", 2: "b", 3: "c", 4: "d"}。如果我们想要按照降序排序,可以使用std::greater为std::map的第三个模板参数,即std::map<int, std::string, std::greater<int>> t;。这样,t中的键值对的顺序将按照key的降序排序,即{4: "d", 3: "c", 2: "b", 1: "a"}。 关于std::map与std::unordered_mapkey为字符串的问题,可能是你在使用时遇到了一些困惑。如果有具体的问题或示例代码,可以提供更多细节,我可以帮助你解决。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [利用std::map和std::greater对key进行降序排列](https://blog.csdn.net/hp_cpp/article/details/109294914)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++ map 根据value找key的实现](https://download.csdn.net/download/weixin_38647039/13759929)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C++ std::map 与 std::unordered_mapkey 为 字符串的一些问题](https://blog.csdn.net/linjf520/article/details/107265219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值