轉自:https://www.cnblogs.com/chanshuyi/p/4468470.html
一、Set接口
Set 接口與 List 接口相比沒有那麼多操作方法,比如:
1、List 接口能直接設定或擷取某個元素的值,而Set接口不能。
2、List 接口能直接在指定位置删除、增加元素,而Set接口不能。
3、List 接口有 listIterator 方法,可以獲得 ListIterator 對象,而 Set 接口不能。Set 隻能通過 iterator 疊代的方式擷取元素。
對比一下Set接口和Collection接口就知道,其實Set接口僅僅對Collection所有方法進行繼承而已,而自己沒有擴充任何方法,Set接口與Collection接口一樣,都是15個方法。
Set不允許包含相同的元素,如果試圖把兩個相同元素加入同一個集合中,add方法傳回false。這裡說的相同元素指的是用 equals() 方法比價後傳回 true,當然了如果用 == 也傳回true,那肯定也是相同的。
二、HashSet實作類
HashSet 實作類與 Set 接口在方法上的唯一差別就是 HashSet 多了一個clone()方法。
hashSet 有以下特點:
· 不能保證元素的排列順序,順序有可能發生變化
· 不是同步的
· 集合元素可以是 null,但隻能放入一個 null
一般操作 HashSet 還是調用 Collection 的 add / remove 等方法進行操作
package com.chanshuyi.collection.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetTest {
public static void main(String[] args) {
//增加
Set<String> hashSet = new HashSet<String>();
hashSet.add("1");
hashSet.add("2");
hashSet.add("3");
hashSet.add("4");
hashSet.add("5");
//删除
hashSet.remove("1");
//查詢 無法擷取某個元素
System.out.println("是否包含1元素:" + hashSet.contains("2"));
//疊代
Iterator<String> it = hashSet.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
}
}
當向 HashSet 結合中存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的hashCode值,然後根據 hashCode值來決定該對象在 HashSet 中存儲位置。根據這種方式可以看出,HashSet 的資料存取其實是通過雜湊演算法實作的,因為通過雜湊演算法可以極大的提高資料的讀取速度。通過閱讀 JDK 源碼,我們知道 HashSet 是通過 HashMap 實作的,隻不過是HashSet 的 value 上的值都是 null 而已。
簡單的說,HashSet 集合判斷兩個元素相等的标準是兩個對象通過 equals() 方法比較相等,并且兩個對象的hashCode() 方法傳回值相等。
注意,如果要把一個對象放入 HashSet 中,重寫該對象對應類的 equals() 方法,也應該重寫其 hashCode() 方法。其規則是如果兩個對 象通過equals方法比較傳回true時,其hashCode也應該相同。另外,對象中用作equals比較标準的屬性,都應該用來計算hashCode的值。
三、LinkedHashSet實作類
LinkedHashSet類繼承了HashSet類,實作了Set接口。其操作方法也是跟HashSet一樣,全部來自于Set接口,一共有15個方法。
LinkedHashSet 集合同樣是根據元素的 hashCode 值來決定元素的存儲位置,但是它同時使用連結清單維護元素的次序。
這樣使得元素看起來像是以插入順序儲存的,也就是說,當周遊該集合時候,LinkedHashSet将會以元素的添加順序通路集合的元素。
LinkedHashSet 在疊代通路 Set 中的全部元素時,性能比 HashSet 好,但是插入時性能稍微遜色于HashSet(因為 HashSet 直接采用雜湊演算法,而 LinkedHashSet 還需要維護連結清單結構)。
package com.chanshuyi.collection.set;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
//增加
LinkedHashSet<String> linkedSet = new LinkedHashSet<String>();
linkedSet.add("1");
linkedSet.add("2");
linkedSet.add("3");
linkedSet.add("4");
//删除
linkedSet.remove("2");
//查詢 無法擷取某個确定元素,沒有get()方法
System.out.println("是否包含元素4:" + linkedSet.contains("4"));
for(String num : linkedSet){
System.out.print(num + " ");
}
}
}
四、TreeSet實作類
TreeSet 是 SortedSet 接口的唯一實作類,TreeSet 可以確定集合元素處于排序狀态,這也是 TreeSet最大的特征之一。
TreeSet支援兩種排序方式,自然排序和定制排序,其中自然排序為預設的排序方式。向TreeSet中加入的應該是同一個類的對象。插入 TreeSet 中的對象使用一個外部比較器或者對象實作排序接口。
1、JavaBean中實作Comparable接口的compareTo()方法
自然排序使用要排序元素的 CompareTo(Object obj)方法來比較元素之間大小關系,然後将元素按照升序排列。
Java提供了一個 Comparable 接口,該接口裡定義了一個 compareTo(Object obj) 方法,該方法傳回一個整數值,實作了該接口的對象就可以比較大小。
obj1.compareTo(obj2) 方法如果傳回 0,則說明被比較的兩個對象相等,如果傳回一個正數,則表明obj1大于obj2,如果是 負數,則表明obj1小于obj2。
如果我們将兩個對象的equals方法總是傳回true,則這兩個對象的 compareTo 方法傳回應該傳回0
package com.chanshuyi.collection.set;
import java.util.TreeSet;
/**
* 構造JavaBean并實作Comparable接口的compareTo方法
* @author Administrator
*/
public class TreeSetTest2 {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>();
treeSet.add(new Student("Tpple", 12));
treeSet.add(new Student("Tpple", 10));
for(Student s : treeSet){
System.out.println(s);
}
}
}
class Student implements Comparable<Student>{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = 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;
}
@Override
public int compareTo(Student s) {
if(this.age > s.getAge()){
return 1; //按照自然排序
}else if(this.age == s.getAge()){
return 0;
}else{
return -1;
}
}
public String toString(){
return "[" + this.name + "," + this.age + "]";
}
}
2、建構自定義比較器(實作Comparator接口)
自然排序是根據集合元素的大小,以升序排列,如果要定制排序,應該使用Comparator接口,實作 int compare(T o1,T o2)方法
package com.chanshuyi.collection.set;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetTest3 {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>(new MyComparator());
treeSet.add(new Student("Tpple", 12));
treeSet.add(new Student("Tpple", 10));
for(Student s : treeSet){
System.out.println(s);
}
}
}
class MyComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
if(o1.getAge() > o2.getAge()){
return 1;
}else if(o1.getAge() == o2.getAge()){
return 0;
}else{
return -1;
}
}
}