Day09_43_Set集合_HashSet_02(HashCode方法 与 equals方法 )

HashSet

 - 向Hash表中添加元素的过程?
        
          1. 先调用将要被存储的值key的HashCode方法得出Hash值,如果该Hash值在现有Hash表中不存在,那么直接加入元素。
       
          2. 如果该Hash值已经存在于当前hash表中,那么就需要继续调用key的equals()方法,如果equals()方法返回false,证明该key的值和哈希表中当前数组元素中的链表中的数据的值不相等,又因为Set集合的特定点 
             是无序不可重复,所以只有Key值和已存在于链表中的值不相等的情况下才能将该Key添加进去。

          3. 如果key调用equal()方法返回true,证明该key值和哈希表当前数组元素中的链表中的值存在重复,则放弃添加。

- 当我们向set集合中添加值相等的对象(key)时,为什么可以添加进去呢?

        * 因为该对象类中没有重写HashCode()方法,两条数据的数据值虽然相同,但是两条数据的内存地址是不同的,所以得到的HashCode值也是不同的。所以就需要在该类中重写HashCode方法。
 
        * 如果想要equals()方法百分之百被执行,怎么办?
          
            - 重写HashCode()方法,让HashCode()方法返回一个固定值就可以了, 因为当Set集合中的所有元素的hashCode值都相等的时候,就会使用equals方法继续比较。

            - 但是这样操作就会造成一个问题,因为所有元素的hashCode值都是相等的,hashCode值又指向了底层hash表中数组的下标,当hashCode值相等的时候,也就指向了数组中的同一个元素,所以加进去的所有元素都 
              会加在一个单向链表上,这样底层的hash表也就失去了意义。所以hashCode()方法不能返回一个固定值。

- 存储在HashSet集合 或者 HashMap集合中的元素,需要同时重写HashCode()方法 和 HashMap()方法

- 重写HashCode()方法,要尽量做到散列均匀分布,以便数据合理存储,提高检索效率。




- 代码实例

 ```
  员工类
 
           public class Employee {

            //属性
            String empno;   // 规定 该公司员工编号是 1000~9999
            String ename;

            // 构造方法
            Employee(){}
            Employee(String empno,String ename){
                this.empno=empno;
                this.ename=ename;
            }


            // 重写equals()方法   如果员工的姓名和员工号都相等那么就返回true
            public boolean equals(Object object){
              if(this==object){
                  return true;
              }
              if(object instanceof Employee){
                  Employee employee=(Employee) object;
                  if(employee.empno.equals(this.empno) && employee.ename.equals(this.ename)){
                      return true;
                  }
              }
              return false;

            }



            // 重写HashCode()方法  重写HashCode()方法 只有一个目的,那就是尽量做到散列均匀分布。

            // 如果想要equals()方法百分之百被执行,那么HashCode返回一个固定值就可以了。
            // 因为当Set集合中的所有元素的hashCode值相等的时候,就会使用equals方法继续比较。
            // 但是这样操作就会造成一个问题,因为所有元素的hashCode值都是相等的,所以加进去的所有元素都会加在一个单向链表上,这样底层的hash表也就失去了意义。

             public int hashCode(){

                  //以员工编号分组,将String类型的empno转换为int类型。然后除以1000,那么所有编号为1的是一组,为2的是一组,以此类推。
                  int groupId= Integer.parseInt(empno.toString());
                  return groupId/1000;

             }


             //重写toString方法
              @Override
              public String toString() {
                  return "Employee{" +
                          "empno='" + empno + '\'' +
                          ", ename='" + ename + '\'' +
                          '}';
              }
      }

 ```
      主类:
         
      mport java.util.HashSet;
      import java.util.Iterator;
      import java.util.Set;

      public class SetTest02 {
          public static void main(String[] args) {

              //创建员工set集合
              Set emp= new HashSet(); //父类引用指向子类对象

              // 创建员工对象
              Employee employee1=new Employee("1000","Smith");
              Employee employee2=new Employee("1001","Eva");
              Employee employee3=new Employee("1002","Morty");
              Employee employee4=new Employee("1003","Rick");
              Employee employee5=new Employee("1004","Michael");
              Employee employee6=new Employee("2000","Jack");
              Employee employee7=new Employee("3000","Mike");


              // 添加元素
              emp.add(employee1);
              emp.add(employee2);
              emp.add(employee3);
              emp.add(employee4);
              emp.add(employee5);

              // 查看集合中的元素个数
              int empNumber=emp.size();
              System.out.println(empNumber);

              // 此时再向集合中加入一条数据,该条数据和上面的数据重合
              //emp.add(employee6);
              System.out.println(emp.size()); //6

              // 获取HashCode
              System.out.println(employee1.hashCode()); //460141958
              System.out.println(employee2.hashCode()); //21685669

              // 集合长度输出为6,证明和集合中已有数据值相同的最后一条数据也成功加载到了Set集合中,可是Set集合是无序不可重复的集合,为什么可以加进去呢?
              // 因为: 没有重写HashCode()方法,两条数据的数据值虽然相同,但是两条数据的内存地址是不同的,所以得到的HashCode值也是不同的。所以需要重写HashCode方法

              //再次向集合中添加元素
              emp.add(employee6);
              emp.add(employee7);
              System.out.println(emp.size());

              //遍历集合
              Iterator iterator=emp.iterator();
              while(iterator.hasNext()){
                  System.out.println(iterator.next());
              }

              // 获取HashCode
              System.out.println(employee3.hashCode());  // 1
              System.out.println(employee4.hashCode());  // 1
              System.out.println(employee6.hashCode());  // 2
              System.out.println(employee7.hashCode());  // 3

          }
      }
posted @ 2021-04-03 13:47  失昼  阅读(62)  评论(0)    收藏  举报