Java學習筆記31(集合框架五:set接口、哈希表的介紹)
set接口的特點:
1.不包含重復元素
2.set集合沒有索引,只能用叠代器或增強for循環遍歷
3.set的底層是map集合
方法和Collection的方法基本一樣
set接口的實現類HashSet:
1.無序集合
2.可以存入空(null)
3.不可以存在重復元素
示例:
package demo; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class HashSetDemo { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("abc1"); set.add("abc1"); set.add("abc2"); set.add("abc3"); set.add("abc4"); Iterator<String> i1 = set.iterator(); while(i1.hasNext()){ System.out.println(i1.next()); } } }/* 輸出: 註意:這裏的輸出特點是無序的 abc1 abc4 abc2 abc3 */
set底層數據結構是哈希表:
特點:存儲取出都比較快
原理:具體省略,簡單說就是鏈表數組結合體
對象的哈希值:普通的一個整數
可以理解為身份證號,是hashset存儲的依據
package demo; public class Person {}
package demo; public class HashDemo { public static void main(String[] args) { Person p = new Person();int i = p.hashCode(); System.out.println(i); //每次運行都會輸出不同的整數,比如1191201656 String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1.hashCode());//96354 System.out.println(s2.hashCode());//96354 //這裏Stirng重寫hashcode方法,有對應的計算公式 //當字符串的內容相同時候,運算結果就相同,因此s1和s2的哈希值相同 } }
哈希表存儲過程:
1.調用對象的哈希值
2.集合在容器內搜索有沒有重復的哈希值,如果沒有,存入新元素,記錄哈希值
3.再次存儲,重復上邊的過程
4.如果有重復的哈希值,調用後來者的equals方法,參數為前來者,結果得到true,集合判斷為重復元素,不存入
相同的字符串如果存進去,哈希值相同,equals方法為true,不會存入相同的
只要哈希值相同或者equals方法為true都成立才不會存入,只要其中一條不滿足,都會儲存
哈希表存儲自定義對象:
package demo; public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } }
package demo; import java.util.HashSet; public class HashDemo { public static void main(String[] args) { HashSet<Person> setPerson = new HashSet<Person>(); setPerson.add(new Person("a",17)); setPerson.add(new Person("b",20)); setPerson.add(new Person("b",20)); setPerson.add(new Person("c",18)); System.out.println(setPerson); //[c:18, b:20, a:17, b:20] //發現存入了重復的元素 //所以想辦法使name和age相同的Person對象視為同一個對象 //所以需要重寫hashcode方法 } }
自己重寫:
package demo; public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } public int hashCode(){ return name.hashCode()+age*66; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof Person) { Person p = (Person) obj; return name.equals(p.name) && age == p.age; } return false; } }
eclipse可以幫助我們寫:
package demo; public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } @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; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
LinkedHashSet集合:基於鏈表的哈希表實現,繼承HashSet,它具有順序
示例:
package demo; import java.util.LinkedHashSet; public class LinkedHashSetDemo { public static void main(String[] args) { //有序的set LinkedHashSet<Integer> link = new LinkedHashSet<Integer>(); link.add(1); link.add(2); link.add(3); link.add(4); System.out.println(link); //[1, 2, 3, 4] } }
關於hashcode和equals的一些問題,在面試中會問道:
1.兩個對象哈希值相同,那麽equals方法一定返回true嗎?不一定
取決於如何重寫equals,如果重寫固定了它返回false,結果就一定是false
2.equals方法返回true,那麽哈希值一定相同嗎?一定
如果類中定義一個靜態變量(static int a = 1),然後重寫hashcode返回a+1,那麽每一個對象的哈希值都不一樣
不過java中規定:對象相等,必須具有相同的哈希碼值,所以這裏是一定的
Java學習筆記31(集合框架五:set接口、哈希表的介紹)