韩顺平集合课后作业Homework06.java探讨

家庭作业06
看了韩顺平老师的视频获益匪浅,但是这里有点不太懂,希望会的大神能帮助解答一下。第二次输出前的:set.add(new Person(1001,“CC”));为啥能add进HashSet中这里我很疑惑,自己看了源码打了断点还是有一些疑问,希望能帮我解答一下。自己仿照幻灯片的示例敲了一下代码。

package com.HomeWork;

import org.junit.Test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Objects;
import java.util.TreeSet;

/**
 * @author 心向阳光的天域
 * @date 2022/10/10 17:56
 */
public class HomeWork06 {
    @Test
    @SuppressWarnings({"all"})
    public void getHomeWork06() {
        People p1 = new People("1001", "AA");
        People p2 = new People("1002", "BB");
        HashSet hashSet = new HashSet();
        hashSet.add(p1);
        hashSet.add(p2);
        System.out.println("正常情况" + p1.hashCode()); //
        p1.name = "CC"; // 因为重写了hashCode,所以name变了之后hash值就会变
        System.out.println("修改p1为CC后:" + p1.hashCode()); //

        hashSet.remove(p1); // hash值变了之后,删除就找不到以前的p1了

        System.out.println("----第一次输出----");
        System.out.println(hashSet);

        People p3 = new People("1001", "CC"); // hashCode:
        System.out.println("p3的hashCode值:" + p3.hashCode()); //
        hashSet.add(p3); // 为啥这里add可以插进去?????????

        System.out.println("----第二次输出----");
        System.out.println(hashSet);

        hashSet.add(new People("1001", "AA")); // 这次

        System.out.println("----第三次输出----");
        System.out.println(hashSet);


    }

class People {
    private String id;
    public String name;

    public People(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        People people = (People) o;
        return Objects.equals(id, people.id) && Objects.equals(name, people.name);
    }

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

    @Override
    public String toString() {
        return "People{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

运行结果
这里可以明显看到p1对象的hashCode和p3的hashCode一样。但是Debug之后出现了如下图的情况:
存在问题
这里可以看到绿框框起来的p1对象和p3对象name对应的hash值是完全一样的,但是红框里的hashCode值又不一样,于是我追了一下源码看了看红框里hash值的计算规则。
如下代码所示:

	hashSet.add(p3); // 主要是add代码追进源码看

	//源码HashMap.class中
	//static class Node<K, V> implements Entry<K, V>
        Node(int var1, K var2, V var3, HashMap.Node<K, V> var4) {
            this.hash = var1; // 这里就是红框中的hash值
            this.key = var2;
            this.value = var3;
            this.next = var4;
        }
    // 而这里的var1也可以追溯源码HashMap.class中put方法
        public V put(K var1, V var2) {
        return this.putVal(hash(var1), var1, var2, false, true); // 这里可以看到Node的var1是来自add对象的hash方法
        }

	// 继续往下看hash方法的计算
    static final int hash(Object var0) { // 这里var0就是add后对象p3
        int var1;
        return var0 == null ? 0 : (var1 = var0.hashCode()) ^ var1 >>> 16; // 这里p1和p3的hashCode相同,为什么最后出来的红框中hash值却不同
    
    }

问题就是最后跟到源码,发现hash值的计算规则,就是分别拿p1和p3的哈希值进行按位与操作,这里是真的不懂为什么红框里计算出来的hash值为什么会不同,以及怎么理解这里能add进去的问题,希望会的大神能帮助解决一下我的困难,感谢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心向阳光的天域

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值