黑馬程序員_

--------------------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培訓、期待與您交流! --------------------


發佈了46 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章