A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

    hashset 容器中只能存储不重复的对象,而说到其中的原理,就不得不提到哈希表的存储结构,与一般的数组和链表,栈的存储结构不同 ,哈希表的存储并不是顺序存储,存入其中的元素 ,他们的地址并不一定是连续的,而是按照元素的特点,通过固定的公式,将元素的哈希值算出之后,根据哈希值来安排他们的存储地址,当hashset在存储数据时,首先,根据元素来算出 哈希值,不同的哈希值一定是不同的元素,存入hashset中,如果哈希值相同,再来进行比较,如果真的相同 ,就放弃存储 ,如果相同就不再存入,大家可以发现这样很大程度上减少了元素之间的比较次数,用不着将对象与别的对象依次比较。
    这种算法有点像幼儿园里,小朋友们的排排坐吃果果的理论,小朋友不可能像大人一样乖乖听话,自觉主动的做好,怎么给他们安排座位呢,这样吧 ,先按个头,个头大的坐在前面,个头小的坐在后面,如果有小朋友跑过来 说跟某个座位的人身高一样,我们就把他和那个座位的小朋友比较一下,是否是同一个人,如果不是,就再给这个孩子安排一个作为,如果是,就只在这个座位上。
    这里面涉及到两个方法,一个是得出哈希值的方法 ,一个是比较的方法。当hashset存储的是基本数据类型的包装类对象时
             HashSet<String> hs = new HashSet<>();     //创建HashSet对象
              hs.add("a");
              hs.add("a");     
              hs.add("b");
              hs.add("c");
              hs.add("d");

    string 类 中的hashCode(),equals() 方法 ,会根据字符串的字典顺序,进行排序,而后比较。
而当 hashset  中 存储的是自定义对象时 :
HashSet<Person> hs = new HashSet<>();
  hs.add(new Person("张三", 23));
  hs.add(new Person("张三", 23));
  hs.add(new Person("李四", 24));
  hs.add(new Person("李四", 24));
  hs.add(new Person("李四", 24));
  hs.add(new Person("李四", 24));

这时候,如果person类如果只声明name, age 属性,在存储这六条数据时,都会存入hashset ,只是由于,person类没有重写父类的hashcode() ,和equal()方法,它是按照在堆内存中开辟的地址值来存储的,相同属性的对象它的地址值是不同的,所以都会存入。所以要想用属性值来区别不同的对象需要重写父类的hashcode() ,和equal()方法
@Override
public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + age;
  result = prime * result + ((name == null) ? 0 : name.hashCode());
  return result;
}
@Override
public boolean equals(Object obj) {
  if (this == obj)      //调用的对象和传入的对象是同一个对象
   return true;      //直接返回true
  if (obj == null)      //传入的对象为null
   return false;      //返回false
  if (getClass() != obj.getClass())  //判断两个对象对应的字节码文件是否是同一个字节码
   return false;      //如果不是直接返回false
  Person other = (Person) obj;   //向下转型
  if (age != other.age)     //调用对象的年龄不等于传入对象的年龄
   return false;      //返回false
  if (name == null) {      //调用对象的姓名为null
   if (other.name != null)    //传入对象的姓名不为null
    return false;     //返回false
  } else if (!name.equals(other.name)) //调用对象的姓名不等于传入对象的姓名
   return false;      //返回false
  return true;       //返回true
}
  

2 个回复

倒序浏览
66666666666666666666666666
回复 使用道具 举报
6666666666666666666
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马