• Java HashSet


    Set集合,先从HashSet学起。

    1.HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构。

    2.哈希表又叫做散列表,哈希表底层是一个数组,这个数组中每一个元素是一个单向链表,每一个单向链表都有一个独一无二的hash值,代表数组的下标。在某个单向链表中的每一节点上的hash值是相等的,hash值实际上是key调用hashCode方法,再通过“hash function”转换成的值。

    3.如何向哈希表中添加元素:

    先调用被存储的key的hashCode方法,经过某个算法得出hash值,如果在这个哈希表中不存在这个hash值,则直接加入元素。如果该hash值已经存在,继续调用key之间的equals方法,如果equals方法返回false,则将该元素添加,如果equals方法返回true,则放弃添加该元素。

    4.HashSet其实是HashMap中的key部分,HashSet有什么特点,HashMap中的key应该有相同的特点。

    5.HashMap和HashSet的初试化容量都是16,默认加载因子是0.75.

    结合下面这个程序来看。

    import java.util.*;
    public class HashSetTest01{
     public static void main(String[] args){
       //创建Set集合
       Set s=new HashSet();
       //添加元素
       s.add(1);
       s.add(1);
       
       s.add(23);
       s.add(3);
       s.add(10);
       
       Iterator it=s.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
       }
     }
    }

    编译运行后输出:

    1
    3
    23
    10

    上述代码中,首先创建一个Set集合s,然后用add()方法向其中添加元素,之后使用迭代器对其进行迭代并且输出其中的元素。从编译运行输出的结果我们可以看出,Set集合是无序并且不可重复的。

    接下来看看看关于往Set集合中存储的元素,该元素的hashCode和equals方法。结合以下代码来看:

    import java.util.*;
    public class HashSetTest02{
     public static void main(String[] args){
       //创建Set集合
       Set es=new HashSet();
       //创建Employee类型的对象
       Employee e1=new Employee("1000","JACK");
       Employee e2=new Employee("1000","JACK");
       Employee e3=new Employee("2000","JSDD");
       Employee e4=new Employee("2001","CJS");
       Employee e5=new Employee("3000","sdc");
       Employee e6=new Employee("3001","mdwkm");
       //Set集合中添加元素
       es.add(e1);
       es.add(e2);
       es.add(e3);
       es.add(e4);
       es.add(e5);
       es.add(e6);
       //输出Set集合元素的个数
       System.out.println(es.size());
       //查看e1,e2的hashCode()方法
       System.out.println(e1.hashCode());
       System.out.println(e2.hashCode());
     }
    }
    //根据现实的业务逻辑得知,该公司的员工编号是:1000-9999
    class Employee{
     String no;
     String name;
     Employee(String no,String name){
       this.no=no;
       this.name=name;
     }
    }

    编译运行后输出:

    6
    366712642
    1829164700

    上述代码中:

    1.首先创建一个Set集合es,接着创建六个Employee类型的对象,e1和e2的工号和名字相同,从编译运行后的结果可以看出,e1和e2都被添加到Set集合当中去了,在现实中出于实际需要的考虑,e2不应该被添加进去,因此必须重写Object中的hashCode()方法(Object中的方法一般都是让我们根据现实业务的需要重写的)。

    2.重写hashCode()方法有固定的技巧,在上面代码实例中,以员工编号分组重写hashCode()方法,使其散列均匀分布。

    public int hashCode(){
     return no.hashCode();
    }

    3.当hashCode方法返回的值不同时,可以直接往集合中添加元素。当hashCode方法返回的值相同时,需要调用equals()方法,这里需要我们重写equals()方法。

    public boolean equals(Object o){
       if(this==o){
         return true;
       }
       if(o instanceof Employee){
         Employee e=(Employee)o;
         if(e.no.equals(this.no) && e.name.equals(this.name)){
           return true;
         }
       }
       return false;
     }

    整个的代码如下所示:

    import java.util.*;
    public class HashSetTest02{
     public static void main(String[] args){
       //创建Set集合
       Set es=new HashSet();
       //创建Employee类型的对象
       Employee e1=new Employee("1000","JACK");
       Employee e2=new Employee("1000","JACK");
       Employee e3=new Employee("2000","JSDD");
       Employee e4=new Employee("2001","CJS");
       Employee e5=new Employee("3000","sdc");
       Employee e6=new Employee("3001","mdwkm");
       //Set集合中添加元素
       es.add(e1);
       es.add(e2);
       es.add(e3);
       es.add(e4);
       es.add(e5);
       es.add(e6);
       //输出Set集合元素的个数
       System.out.println(es.size());
       //查看e1,e2的hashCode()方法
       System.out.println(e1.hashCode());
       System.out.println(e2.hashCode());
     }
    }
    class Employee{
     String no;
     String name;
     Employee(String no,String name){
       this.no=no;
       this.name=name;
     }
     //重写equals方法
     //如果员工编号相同,并且名字相同,则是同一个对象
     public boolean equals(Object o){
       if(this==o){
         return true;
       }
       if(o instanceof Employee){
         Employee e=(Employee)o;
         if(e.no.equals(this.no) && e.name.equals(this.name)){
           return true;
         }
       }
       return false;
     }
     
     //重写hashCode方法
     public int hashCode(){
       return no.hashCode();
     }
    }

    重写hashCode和equals方法之后,编译运行输出:

    5
    1507423
    1507423

    从上面的结果可以看出,当出现相同的员工编号和姓名时,只会添加进去一个对象,实现了现实业务的需求。

  • 相关阅读:
    Jzoj3895 数字对
    Jzoj3895 数字对
    Jzoj3894 改造二叉树
    Jzoj3894 改造二叉树
    Jzoj3883 线段树
    Jzoj3883 线段树
    Jzoj3882 近邻
    Jzoj3882 近邻
    第三十一天 how can I 坚持
    第三十天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/naihuangbao/p/9444489.html
Copyright © 2020-2023  润新知