• 黑马程序员_<<Set,HashSet>>


    --------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


    1.Set

           Set是Collection接口的子接口,此集合中不能存放重复元素,对于比较方式是根据他们的底层结构决定的,常见的子类有:HashSet和TreeSet

    2.HashSet

         1. 概述

         底层是哈希表:哈希值是Object类中哈希方法返回的值,读取此集合中的元素是必须使用迭代器,比较的时候,先是比较的哈希值,如果哈希值相同那么就比较equals方法。

       2. 无序性

        

       

     package www.fuxi.jihe;
     
    import java.util.HashSet;
    import java.util.Iterator;
     
    public class HashSetDemo {
      public static void main(String[]args) {
        HashSet set = new HashSet();// HashSet对象
        set.add("java01");
        set.add("java02");// 添加元素
        set.add("java03");
        Iterator it = set.iterator();// 迭代器读取数据
        while (it.hasNext()) {
          System.out.println(it.next());
        }
     
      }
     
    }
    结果:
    java02
    java03
    java01
     

    从结果可以看出,他们的读取出来的顺序和存入的顺序是不同的,所以说明他们元素是无序的。


         3. 不可重复性


      

     package www.fuxi.jihe;
    import java.util.HashSet;
    import java.util.Iterator;
    public class HashSetDemo {
      public static void main(String[] args) {
        HashSet set = new HashSet();// HashSet对象
        set.add("java01");
        set.add("java02");// 添加元素
        set.add("java03");
        System.out.println("java02是否存储集合中:"+set.add("java02"));
        Iterator it = set.iterator();// 迭代器读取数据
        while (it.hasNext()) {
          System.out.println(it.next());
        }
     
      }
     
    }
    结果:
    java02是否存储集合中:false
    java02
    java03
    java01
    从结果可以看出他们java02没有存储里面,所以,集合中不能存储相同的元素


    4.比较的原理


         他们首先比较的哈希值,如果哈希值相同,那么他们就开始比较他们的equals方法,同时也可以自定义比较规则,就是重写HashCode()和equals()方法。

       重写的时候一定要和Object类中定义的一样,equals的参数是Object类型,public boolean equals(Object ob){},public int hashCode();

     

          在这里也说一下ArrayList和LinkedList集合,他们的比较方式,他们就是基于equals方法



     

    package www.fuxi.jihe;
    public class Person {
      private String name;// 姓名
      private int age;// 年龄
     
      public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
      }
     
      public String getName() {
        return name;
      }
     
      public int getAge() {
        return age;
      }
     
      /*
       * 这个重写hashCode()方法,在这里返回的哈希值是一样的,为了测试是不是调用的此方法,若哈希值相同,调用的是否是equals()方法
       */
      public int hashCode() {
        System.out.println(this.getName() + "--hashCode()");
        return 20;
      }
     
      /* equals()方法重写 */
      public boolean equals(Object ob) {
        if (!(ob instanceof Person)) {
          return false;
        }
     
        Person p = (Person) ob;
        System.out.println(this.getName() + "--equals---" + p.getName());
        return this.name.equals(p.name) && this.age == p.age;
      }
    }
    package www.fuxi.jihe;
    import java.util.HashSet;
    import java.util.Iterator;
    public class HashSetDemo {
      publicstatic void main(String[] args) {
           HashSetset = new HashSet();// HashSet对象
           set.add(newPerson("zhangsan",21));
           set.add(newPerson("lisi",22));// 添加元素
           set.add(newPerson("zhangsan",21));
          
           System.out.println("读取集合中的元素:");
           Iteratorit = set.iterator();// 迭代器读取数据
           while(it.hasNext()) {
                 Personob=(Person)it.next();
                 System.out.println(ob.getName()+":"+ob.getAge());
           }
     
      }
     
    }
    结果:
    zhangsan--hashCode()
    lisi--hashCode()
    lisi--equals---zhangsan
    zhangsan--hashCode()
    zhangsan--equals---lisi
    zhangsan--equals---zhangsan
    读取集合中的元素:
    lisi:22
    zhangsan:21


     从结果中可以看出,每次存储对象后,都会调用hashCode()方法,在这个哈希值都一样,所以她们都会再次调用equals方法,

     但是如果你没有重写hashCode()方法,那么每次添加新的对象若都使用了new创建的对象,那么他们的hashCode()的是不一样,所以我们可以自定义hashCode和equals方法

     

    如果我们hashCode()方法重写的恰到好处的话,那么equals方法减少了比较次数。

     

     

    package www.fuxi.jihe;
     
    public class Person {
      private String name;// 姓名
      private int age;// 年龄
     
      public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
      }
     
      public String getName() {
        return name;
      }
     
      public int getAge() {
        return age;
      }
     
      /*
       * 重写hashCode()方法,这样的哈希值差不多都很难不一样的
       */
      public int hashCode() {
        return this.name.hashCode()+this.age*56;
      }
     
      /* equals()方法重写 */
      public boolean equals(Object ob) {
        if (!(ob instanceof Person)) {
          return false;
        }
     
        Person p = (Person) ob;
        System.out.println(this.getName() + "--equals---" + p.getName());
        return this.name.equals(p.name) && this.age == p.age;
      }
    }
     


    在这里说一下,对于集合存储的自定义对象,那么使用读取出来的是Object类型,所以我们要是使用对象的方法,那么我需要把其强制类型转换为我们需要的类型。

     
    3. HashSet的删除和判断

          

    package www.fuxi.jihe;
     
    public class Person {
      private String name;// 姓名
      private int age;// 年龄
     
      public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
      }
     
      public String getName() {
        return name;
      }
     
      public int getAge() {
        return age;
      }
     
      /*
       * 重写hashCode()方法,这样的哈希值差不多都很难不一样的
       */
      public int hashCode() {
        int code = this.name.hashCode() + this.age * 56;
        System.out.println(this.name + ":"+this.age+"---Code=" + code);
        return code;
      }
     
      /* equals()方法重写 */
      public boolean equals(Object ob) {
        if (!(ob instanceof Person)) {
          return false;
        }
     
        Person p = (Person) ob;
        System.out.println(this.getName() + "--equals---" + p.getName());
        return this.name.equals(p.name) && this.age == p.age;
      }
    }
    packagewww.fuxi.jihe;
    importjava.util.HashSet;
    importjava.util.Iterator;
    public classHashSetDemo {
          public static void main(String[] args) {
               HashSet set = new HashSet();//HashSet对象
               set.add(newPerson("zhangsan",21));
               set.add(newPerson("lisi",22));// 添加元素
               set.add(newPerson("zhangsan",21));
              
               System.out.println("是否存此对象:"+set.contains(new Person("lisi",22)));
     
               System.out.println("是否存此对象:"+set.contains(newPerson("wangwu",20)));
              
               System.out.println("移除此对象:"+set.remove(newPerson("zhangsan",21)));
          }
     
    }
    结果:
    zhangsan:21---Code=-1432603380
    lisi:22---Code=3323235
    zhangsan:21---Code=-1432603380
    zhangsan--equals---zhangsan
    lisi:22---Code=3323235
    lisi--equals---lisi
    是否存此对象:true
    wangwu:20---Code=-795135871
    是否存此对象:false
    zhangsan:21---Code=-1432603380
    zhangsan--equals---zhangsan
    移除此对象:true

    从结果中可以看出也是在判断的时候也是依赖于hashCode()和equals()方法,在这里hashCode()方法设置的比较巧妙,哈希值都不一样,所以没有机会执行equals方法

    --------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


  • 相关阅读:
    MySQL RR隔离 读一致性
    C++奥赛一本通刷题记录(高精度)
    CodeVs天梯之Diamond
    CodeVs天梯之Gold
    CodeVs天梯之Silver
    CodeVs天梯之Bronze
    【2018.1.14】本蒟蒻又回来了
    test
    UVa12545
    UVa1149
  • 原文地址:https://www.cnblogs.com/pangblog/p/3331199.html
Copyright © 2020-2023  润新知