Java中接口Set的特點及方法說明
接口Set的特點及方法
1、特點:無序,不可重復;
2、實現(xiàn)類:添加的方法:
add(Object obj);
addAll(Collection c);
Set中沒有修改的方法,可以間接修改,先刪除再添加;
刪除的方法:
remove(Object obj);
removeAll(Collection c);
retainAll(Collection c)
僅保留set中那些包含在指定的Collection中的元素;clear()
清除所有元素;
查詢的方法:
contains(Object obj)
查詢set中是否包含指定元素,包含返回true;containsAll(Collection c)
查詢set中是否包含指定的多個元素,全部包含返回true;isEmpty()
判斷set是否為空,為空返回true;
3、set集合的遍歷:使用for循環(huán);
使用iterator迭代器:it.hasNext()如果有下一個元素,返回true;
it.next()
返回下一個元素;it.remove()
刪除迭代器返回的最后一個元素;
Set接口及其實現(xiàn)類
Set接口有兩個實現(xiàn)類
- 散列集合:HashSet(Hash算法)
- 樹集合:TreeSet(二叉樹算法)
Set接口:Set存儲元素是無序不可以重復的
HashSet
:元素是否重復是依據(jù):元素自身equals比較進行判定的。TreeSet
:元素是否重復是依據(jù):CompareTo方法返回是否為0。
因為Set接口也是Collection的子接口
所以也可以使用Collection實現(xiàn)的所有方法,其中常用的有:
- 添加:add()
- 刪除:remove()
- 檢查元素是否存在:contains(Object o)
- 迭代器:iterator()
1、TreeSet:樹狀集合、存放有序
語法:Set<E> set = new TreeSet<E>();
說明:TreeSet添加元素時,首先按照compareTo()進行比較,而TreeSet要想指定集合的存放順序,被排序的對象需實現(xiàn)Comparable接口,這個接口強行的對每個實現(xiàn)類對象進行整體的排序,這種排序稱為類的自然排序,這個接口有個抽象方法compareTo,該方法稱為自然排序的方法。
向TreeSet中添加的元素必須是同一個類的。(否則底層調(diào)用compareTo時會報類型轉(zhuǎn)換異常)
public class Person implements Comparable{ int id; int age; String name; public Person(int id,int age,String name){ super(); this.id = id; this.age = age; this.name = name; } public String toString(){ return "Person [id = " + id + ", age = " + age + ", name = " + name + "]"; } @Override public int compareTo(Object o){//按照id排序 Person p; if(o instanceof Pserson){ p = (Person)o; }else{ return -1;//-1代表傳入的參數(shù)比我本身要小 } int diff = this.id - p.id; if(diff!=0){ diff = diff / Math.abs(diff);//差值除以本身絕對值,可以得到+1或-1的值。 } return diff; }
該compareTo方法是根據(jù)對象的id進行比較,也可以根據(jù)自己的需求自定義比較內(nèi)容:
this.id
是當前對象的ido.id
是指定對象的id(也就是傳入對象的id)
調(diào)用sort方法時可以自定義升序或降序:
- 升序:this.id - o.id(this.id < o.id 結(jié)果為負、this.id > o.id 結(jié)果為正,this.id = o.id 結(jié)果為0)
- 降序:o.id - this.id(this.id < o.id 結(jié)果為正、this.id < o.id 結(jié)果為負,this.id = o.id 結(jié)果為0)
上述代碼中,我們使用的是this.id - o.id,所以我們是升序排序的(默認情況就是升序排序的)。
import java.util.Set; import java.util.TreeSet; public class Demo{ public static void main(String[] args){ Set set = new TreeSet(); Person p1 = new Person(1,18,"小明"); Person p2 = new Person(2,5,"小強"); Person p3 = new Person(3,20,"小張"); set.add(p1); set.add(p2); set.add(p3); set.add(p3);//重復的元素不會被添加到集合中 System.out.println(set.size()); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
compareTo方法就是為了實現(xiàn)Comparable接口而存在的,而實現(xiàn)Comparable接口就是為了可以直接使用sort()方法對該對象進行自定義排序。
注意:TreeSet是不能存在null元素(HashSet是可以存儲null值的),向TreeSet中添加元素時,首先按照compareTo()進行比較,元素底層調(diào)用compareTo方法時會報空指針異常。
2、HashSet:散列集合、高效快速
語法:Set<E> set = new HashSet<E>();
說明:HashSet存儲的對象,應該重寫hashCode()和equals()兩個方法,在添加元素的時候會根據(jù)我們重寫hashCode()方法計算元素的hash值,根據(jù)哈希值計算元素存儲的位置(哈希地址),如果該哈希地址沒有元素則會直接添加成功,如果該位置有其他元素會根據(jù)equals方法判斷是否為同一個對象,如果結(jié)果返回true則不會添加,如果為false則會以鏈表的形式追加到該哈希地址處。(底層根據(jù)HashMap實現(xiàn))
在不指定泛型的情況下可以為不同的類型的值;
public class Person{ int id; String name; public Person(int id, String name) { super(); this.id = id; this.name = name; } //重寫hashCode方法只根據(jù)id進行計算hash值 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } //重寫equals方法 @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 (id != other.id) return false; return true; } //重寫toString方法,方便在我們輸出的時候查看 @Override public String toString() { return "Person [id=" + id + ", name=" + name + "]"; } }
public class Demo{ public static void main(String[] args){ Set set = new HashSet(); Person p1 = new Person(1,"小明"); Person p2 = new Person(2,"小張"); Person p3 = new Person(3,"小李"); set.add(p1); set.add(p2); set.add(p3); //在我們添加成功以后修改其決定hash值的id p2.id = 5; //在刪除時會導致刪除不掉(如果修改的是name則不會出現(xiàn)刪除不掉的效果) //因為之前的元素存儲在id為2計算的哈希地址的位置,現(xiàn)在是去id為5計算的哈希地址出去刪除,所以刪除不掉 //set.remove(p2); //會添加到id為5計算的哈希地址,所以會添加成功(雖然屬性相同,但是之前的是存儲在根據(jù)id為2計算的哈希地址位置) set.add(p2); //當我們繼續(xù)添加的時候,equals返回的是true,所以不會添加成功 set.add(p2); //此時創(chuàng)建一個id為2的對象繼續(xù)添加 Person p4 = new Person(2,"小張"); set.add(p4);//會添加id為2計算的哈希地址位置,雖然該位置有元素,但是之前的元素已經(jīng)被修改了,所以會添加成功 System.out.println("集合的長度為:"+set.size()); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
輸出結(jié)果:
集合的長度:5
Person [id=1, name=小明] //根據(jù)id為1計算的哈希地址
Person [id=5, name=小張] //根據(jù)id為2計算的哈希地址(原p2對象以id為2的哈希地址進行存儲,但是后來id被修改為5了)
Person [id=2, name=小張] //根據(jù)id為2計算的哈希地址(p4對象)
Person [id=3, name=小李] //根據(jù)id為3計算的哈希地址
Person [id=5, name=小張] //根據(jù)id為5計算的哈希地址(修改以后的p2以id為5計算的哈希地址存儲)
HashSet存儲元素的存儲過程:
首先說一下HashSet存儲對象的方式:首先根據(jù)我們重寫的HashCode方法計算出Hash值,根據(jù)Hash值來判斷存入Set中的元素是否重復和存儲在Set集合中的哈希地址,如果該Hash地址為空,則會直接將該對象存儲到該哈希地址,如果該哈希地址有元素,會根據(jù)equals方法判斷是否為同一個對象,如果結(jié)果返回true,說明兩個對象是同一對象,則不會添加該對象,如果返回的是false,說明元素本身是不同的,則會以鏈表的形式同時存儲到該哈希地址的位置。
總結(jié):說一下上面的執(zhí)行過程,Set集合是根據(jù)我們重寫的HashCode方法中的屬性,來計算Hash值,來判斷存入Set中的元素是否重復和存儲在Set集合中哈希地址,當我們在存儲之后再進行修改決定計算Hash值的屬性時,會導致程序出現(xiàn)意想不到的結(jié)果,我們首先根據(jù)id為2計算出了一個存儲該對象的哈希地址,當我們修改了id為5后,再進行刪除操作時,它會根據(jù)id為5計算一個Hash值,去該Hash值對應的哈希地址去刪除元素,因為我們之前存儲的哈希地址是根據(jù)id為2計算出來的,所以會導致本應刪除的元素刪除不掉,而當我們再進行add的時候,我們根據(jù)id為5的Hash值去存儲時發(fā)現(xiàn),id為5的地址并沒有元素,所以存儲成功,雖然和之前id為2時計算Hash值存儲位置的元素屬性值一樣,但是還是會存儲成功的,然而,當我們再創(chuàng)建一個id為2的對象進行存儲時,雖然哈希地址相同,但此時之前根據(jù)該哈希地址的對象已經(jīng)改變了(id修改為5了),所以會將新創(chuàng)建的id為2的對象以鏈表的形式同時存儲在該哈希地址的位置,所以當我們操作HashSet集合時,不要去修改決定計算Hash值的元素屬性。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于JAVA中使用Axis發(fā)布/調(diào)用Webservice的方法詳解
如果初識axis發(fā)布/調(diào)用WS,建議先讀上面的參考文件,本文對于發(fā)布/調(diào)用WS的主要步驟只是簡單文字描述,沒有它寫的詳盡2013-05-05java發(fā)送http的get、post請求實現(xiàn)代碼
下面小編就為大家?guī)硪黄猨ava發(fā)送http的get、post請求實現(xiàn)代碼。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05Java調(diào)用打印機的2種方式舉例(無驅(qū)/有驅(qū))
我們平時使用某些軟件或者在超市購物的時候都會發(fā)現(xiàn)可以使用打印機進行打印,這篇文章主要給大家介紹了關(guān)于Java調(diào)用打印機的2種方式,分別是無驅(qū)/有驅(qū)的相關(guān)資料,需要的朋友可以參考下2023-11-11SpringBoot中的@Configuration注解詳解
這篇文章主要介紹了SpringBoot中的@Configuration注解詳解,Spring Boot推薦使用JAVA配置來完全代替XML 配置,JAVA配置就是通過 @Configuration和 @Bean兩個注解實現(xiàn)的,需要的朋友可以參考下2023-08-08