集合的體系:
-----------------Collection 單例集合接口
----------------------List 如果實現的是List接口的集合,具備有序,可重復的特性
-----------------------------ArrayList 底層是維護了一個Object數組實現的。 特點: 查詢速度快,增刪慢。
-----------------------------LinkedList 底層是使用鏈表數據結構實現的,特點:查詢速度慢,增刪塊
-----------------------------Vector 底層維護了一個Object類型的數組,和ArrayList 基本一致,特點:線程安全,但是操作效率低 (出現的早,西安基本被ArrayList 替代了)
----------------------Set 如果實現的是Set接口的集合,具備無序,不可重復的特性
-----------------------------HashSet 底層是使用了哈希表實現的,特點:存取快
-----------------------------TreeSet 底層是使用紅黑樹(二叉樹)存儲的,特點:直接排序(前提是元素具備自然順序的屬性)
-----------------------------------------本文重點對Set集合進行說明------------------------------------------------
HashSet:
存儲的原理:
往HashSet中添加元素的時候,會先調用hashCode()方法,查詢哈希值,然后通過得到的元素的哈希值然后通過移位等運算確定元素的存儲位置;
1、當確定好的元素的位置處沒有其他的元素,則直接將該元素存儲在這個位置
2、當確定好的元素的位置處還有其他的元素,則會先調用元素的equals方法,確認兩個元素是否一致,如果一致認為是重復元素,不會添加成功,如果不一致,繼續添加到該位置處(hash存儲是以桶的形式存儲的,一個位置可以允許有多個元素)
如下是hashSet使用場景,一個簡單的例子
/* 需求:支持從鍵盤輸入用戶名和密碼,如果輸入的用戶名已經存在了 則不允許添加。。。 */ import java.util.HashSet; import java.util.Scanner; class User{ String username; String password; public User(String username,String password){ this.username = username; this.password = password; } @Override //重寫equals方法,設置比較用戶名 public boolean equals(Object obj) { User user = (User) obj; return this.username.equals(user.username); } @Override //重寫toString方法,主要是用來顯示已注冊用戶的(格式自定義) public String toString() { return "{"+username+":"+password+"}"; } @Override //重寫hashCode方法,用用戶名來確定存儲位置 public int hashCode() { return this.username.hashCode(); } } public class hashSetPractise { static HashSet users = new HashSet(); static User user; public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(true){ System.out.println("請輸入用戶名:"); String username= sc.next(); System.out.println("請輸入密碼:"); String password = sc.next(); user = new User(username,password); //add方法返回的是一個boolean類型的數據,true表示添加成功 if(users.add(user)){ System.out.println("注冊成功"); System.out.println("當前注冊的用戶:"+users); }else{ System.out.println("重復注冊了。。"); } } } }
TreeSet:
特點
如果元素具備自然順序 的特性,那么就按照元素自然順序的特性進行排序存儲。
treeSet要注意的事項
1. 往TreeSet添加元素的時候,如果元素本身具備了自然順序的特性,那么就按照元素自然順序的特性進行排序存儲(比如說元素是int類型數據,元素是char類型數據等)
2. 往TreeSet添加元素的時候,如果元素本身不具備自然順序的特性(自定義的元素),那么該元素所屬的類必須要實現Comparable接口,把元素的比較規則定義在compareTo(T o)方法上。
3. 如果比較元素的時候,compareTo方法返回 的是0,那么該元素就被視為重復元素,不允許添加.(注意:TreeSet與HashCode、equals方法是沒有任何關系。)
4. 往TreeSet添加元素的時候, 如果元素本身沒有具備自然順序 的特性,而元素所屬的類也沒有實現Comparable接口,那么必須要在創建TreeSet的時候傳入一個比較器(實際上就是單獨定義一個類實現Comparator接口的的Compare方法)
5. 往TreeSet添加元素的時候,如果元素本身不具備自然順序的特性,而元素所屬的類已經實現了Comparable接口, 在創建TreeSet對象的時候也傳入了比較器那么是以比較器的比較規則優先使用。
使用方法
1、具備自然順序的就不在贅述,能實現自動排序,不需要比較器等其他方法;
2、實現Conparable接口的CompareTo方法實現
import java.util.TreeSet; /* 需求,定義一個員工類並傳入員工,按照工資從小到大排序 */ class Emp implements Comparable{ int id; String name; int salary; public Emp(int id,String name,int salary){ this.id = id; this.name = name; this.salary = salary; } @Override public String toString() { return "{"+id+","+name+","+salary+"}"; } @Override //實現compareTo方法 //這個方法會返回一個負整數,零或正整數,代表該對象小於,等於或大於指定對象。 public int compareTo(Object o) { Emp emp = (Emp) o; return this.salary-emp.salary; } } public class treeSet { public static void main(String[] args) { TreeSet tree = new TreeSet(); tree.add(new Emp(110,"Mary",1800)); tree.add(new Emp(100,"kobe",1500)); tree.add(new Emp(109,"JackJones",3200)); tree.add(new Emp(440,"James",400)); //如果不實現Comparable的compareTo方法,會報錯,因為默認treeSet會進行排序,不指定的話不知道依據什么排序 System.out.println(tree); } }
3、定義一個比較器(推薦使用比較器方法實現,會使代碼更加靈活)
import java.util.Comparator; import java.util.TreeSet; class Emp { int id; String name; int salary; public Emp(int id,String name,int salary){ this.id = id; this.name = name; this.salary = salary; } @Override public String toString() { return "{"+id+","+name+","+salary+"}"; } } /* 定義一個比較器並實現compare方法,方法和compareTo一樣,返回的是負整數,零或者正整數,分別代表小於,等於和大於 */ class MyCompare implements Comparator{ @Override public int compare(Object o1, Object o2) { Emp p1 = (Emp) o1; Emp p2 = (Emp) o2; return p1.id-p2.id; } } public class treeSet { public static void main(String[] args) { MyCompare myCompare = new MyCompare(); TreeSet tree = new TreeSet(myCompare); tree.add(new Emp(110,"Mary",1800)); tree.add(new Emp(100,"kobe",1500)); tree.add(new Emp(109,"JackJones",3200)); tree.add(new Emp(440,"James",400)); System.out.println(tree); } }