程序员Android知识Java学习笔记

弄懂==、equals、hashCode

2018-01-18  本文已影响235人  王小贱_ww

  这篇文章讲一下这3个的知识点,需要对java执行过程中内存过程有点了解,可以看看上一篇文章程序执行过程的内存分析
UserBean类

public class UserBean {

    private String name;
    private int age;
    private String sex;
    private int height;


    public UserBean(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }


}
UserBean user1=new UserBean();
UserBean user2=new UserBean();
System.out.println(user1==user2);
System.out.println(user1.equals(user2));

运行结果:false false
我们先看一下equals的源码:

 public boolean equals(Object obj) {
        return (this == obj);
    }

而==看的是user1和user2的地址,很显然,二者地址不一样,所有都是false。
  如果我们想有自己的比较方式,不想比较地址值,想比较name是否相同,从而判断两个user是否一样,我们应该重写equals方法

  @Override
    public boolean equals(Object obj) {
        UserBean bean = (UserBean) obj;
        return this.name == bean.name;
    }

这样运行的结果是:false true

hashCode

  在讲hashCode之前,先看一段代码:

HashSet hashSet = new HashSet();
hashSet.add(new UserBean("a1", 22));
hashSet.add(new UserBean("a2", 23));
hashSet.add(new UserBean("a3", 24));
hashSet.add(new UserBean("a1", 22));

Iterator iterator = hashSet.iterator();
while (iterator.hasNext()) {
            UserBean userBean = (UserBean) iterator.next();
            System.out.println("name:" + userBean.getName() + "   age:" + userBean.getAge());
        }   

打印的结果:
name:a2 age:23
name:a1 age:22
name:a1 age:22
name:a3 age:24
(图片下面再解释)


1.png

  可以看出1.HashSet没有顺序 2.name为a1 age为22的两个数据应该是重复了,但是还是被添加了进来。。。。。。。我们难道应该重写equals?来判断两个对象是否一样,如果一样,就不添加。

 @Override
    public boolean equals(Object obj) {
        UserBean userBean = (UserBean) obj;
        System.out.println(this.name + "....equals..." + userBean.name);
        return this.name == userBean.name && this.age == userBean.age;
    }

  重写方法后,运行依旧没有 System.out.println(this.name + "....equals..." + userBean.name);打印这个,说明没有走equals方法,这个时候就需要hashcode登场了。

 public int hashCode() {
 System.out.println("...hascode...");
         return  60;
    }
    
    public boolean equals(Object obj) {
        UserBean userBean = (UserBean) obj;
        System.out.println(this.name + "....equals..." + userBean.name);
        return this.name == userBean.name && this.age == userBean.age;
    }

打印结果:

...hascode...
...hascode...
a2....equals...a1
...hascode...
a3....equals...a1
a3....equals...a2
...hascode...
a1....equals...a1
name:a1 age:22
name:a2 age:23
name:a3 age:24


2.png

  在hash表中,1先进来(给个hashcode),2再次进来,hashcode和1的值一样,在判断name和age(二者不一样),得出1和2是两个值,所以把2添加进来,这是因为2和1的hashcode值一样,所以把2挂到1上去。以此类推,最后一个值重复了,所以不添加。
  从效率上来考虑,每次进来都要hashcode 和equals,有点复杂,我们可以根据业务需求,自己建立值,能提高效率

  public int hashCode() {
        System.out.println("...hascode...");
         return  name.hashCode()+age*36;
    }
    
    public boolean equals(Object obj) {
        UserBean userBean = (UserBean) obj;
        System.out.println(this.name + "....equals..." + userBean.name);
        return this.name == userBean.name && this.age == userBean.age;
    }

打印结果:(只比较了一次)
...hascode...
...hascode...
...hascode...
...hascode...
a1....equals...a1
name:a3 age:24
name:a1 age:22
name:a2 age:23


3.png
总结:HashSet怎么能确保数据的唯一性??

  通过hascode和equals,如果hascode元素相同,才会判断equals是否为true,如果hashcode不同,不会调用equals。

上一篇下一篇

猜你喜欢

热点阅读