導航:首頁 > 編程語言 > java中list的set

java中list的set

發布時間:2023-01-25 15:09:58

A. java裡面set,map,list的區別是什麼(盡量詳細)

一、List介面
List是一個繼承於Collection的介面,即List是集合中的一種。List是有序的隊列,List中的每一個元素都有一個索引;第一個元素的索引值是0,往後的元素的索引值依次+1。和Set不同,List中允許有重復的元素。實現List介面的集合主要有:ArrayList、LinkedList、Vector、Stack。

ArrayList
ArrayList是一個動態數組,也是我們最常用的集合。它允許任何符合規則的元素插入甚至包括null。每一個ArrayList都有一個初始容量:

private static final int DEFAULT_CAPACITY = 10;

隨著容器中的元素不斷增加,容器的大小也會隨著增加。在每次向容器中增加元素的同時都會進行容量檢查,當快溢出時,就會進行擴容操作。所以如果我們明確所插入元素的多少,最好指定一個初始容量值,避免過多的進行擴容操作而浪費時間、效率。

size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時間運行。add 操作以分攤的固定時間運行,也就是說,添加 n 個元素需要 O(n) 時間(由於要考慮到擴容,所以這不只是添加元素會帶來分攤固定時間開銷那樣簡單)。

ArrayList擅長於隨機訪問。同時ArrayList是非同步的。

LinkedList
同樣實現List介面的LinkedList與ArrayList不同,ArrayList是一個動態數組,而LinkedList是一個雙向鏈表。所以它除了有ArrayList的基本操作方法外還額外提供了get,remove,insert方法在LinkedList的首部或尾部。

由於實現的方式不同,LinkedList不能隨機訪問,它所有的操作都是要按照雙重鏈表的需要執行。在列表中索引的操作將從開頭或結尾遍歷列表(從靠近指定索引的一端,節約一半時間)。這樣做的好處就是可以通過較低的代價在List中進行插入和刪除操作。

與ArrayList一樣,LinkedList也是非同步的。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:

List list = Collections.synchronizedList(new LinkedList(…));

Vector
與ArrayList相似,但是Vector是同步的。所以說Vector是線程安全的動態數組。它的操作與ArrayList幾乎一樣。

Stack
Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建後是空棧。

二、Set介面
Set是一個繼承於Collection的介面,Set是一種不包括重復元素的Collection。它維持它自己的內部排序,所以隨機訪問沒有任何意義。與List一樣,它同樣運行null的存在但是僅有一個。由於Set介面的特殊性,所有傳入Set集合中的元素都必須不同,關於API方面。Set的API和Collection完全一樣。實現了Set介面的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。

HashSet
HashSet堪稱查詢速度最快的集合,因為其內部是以HashCode來實現的。集合元素可以是null,但只能放入一個null。它內部元素的順序是由哈希碼來決定的,所以它不保證set的迭代順序;特別是它不保證該順序恆久不變。

TreeSet
TreeSet是二叉樹實現的,基於TreeMap,生成一個總是處於排序狀態的set,內部以TreeMap來實現,不允許放入null值。它是使用元素的自然順序對元素進行排序,或者根據創建Set時提供的 Comparator 進行排序,具體取決於使用的構造方法。

LinkedHashSet
LinkedHashSet集合同樣是根據元素的hashCode值來決定元素的存儲位置,但是它同時使用鏈表維護元素的次序。這樣使得元素看起 來像是以插入順序保存的,也就是說,當遍歷該集合時候,LinkedHashSet將會以元素的添加順序訪問集合的元素。LinkedHashSet在迭代訪問Set中的全部元素時,性能比HashSet好,但是插入時性能稍微遜色於HashSet。

三、Map介面
Map與List、Set介面不同,它是由一系列鍵值對組成的集合,提供了key到Value的映射。在Map中它保證了key與value之間的一一對應關系。也就是說一個key對應一個value,所以它不能存在相同的key值,當然value值可以相同。實現map的集合有:HashMap、HashTable、TreeMap、WeakHashMap。

HashMap
以哈希表數據結構實現,查找對象時通過哈希函數計算其位置,它是為快速查詢而設計的,其內部定義了一個hash表數組(Entry[] table),元素會通過哈希轉換函數將元素的哈希地址轉換成數組中存放的索引,如果有沖突,則使用散列鏈表的形式將所有相同哈希地址的元素串起來,可能通過查看HashMap.Entry的源碼它是一個單鏈表結構。

HashTable
也是以哈希表數據結構實現的,解決沖突時與HashMap也一樣也是採用了散列鏈表的形式。HashTable繼承Dictionary類,實現Map介面。其中Dictionary類是任何可將鍵映射到相應值的類(如 Hashtable)的抽象父類。每個鍵和每個值都是一個對象。在任何一個 Dictionary 對象中,每個鍵至多與一個值相關聯。Map是」key-value鍵值對」介面。 HashTable採用」拉鏈法」實現哈希表不過性能比HashMap要低。

TreeMap
有序散列表,實現SortedMap介面,底層通過紅黑樹實現。

WeakHashMap
談WeakHashMap前先看一下Java中的引用(強度依次遞減)

強引用:普遍對象聲明的引用,存在便不會GC
軟引用:有用但並非必須,發生內存溢出前,二次回收
弱引用:只能生存到下次GC之前,無論是否內存足夠
虛引用:唯一目的是在這個對象被GC時能收到一個系統通知
以弱鍵實現的基於哈希表的Map。在 WeakHashMap 中,當某個鍵不再正常使用時,將自動移除其條目。更精確地說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終止,然後被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行為與其他的 Map 實現有所不同。null值和null鍵都被支持。該類具有與HashMap類相似的性能特徵,並具有相同的效能參數初始容量和載入因子。像大多數集合類一樣,該類是不同步的。

四、總結
1、List、Set都是繼承自Collection介面,Map則不是。

2、List特點:元素有放入順序,元素可重復 ,Set特點:元素無放入順序,元素不可重復,重復元素會覆蓋掉,(注意:元素雖然無放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實是固定的,加入Set 的Object必須定義equals()方法 ,另外list支持for循環,也就是通過下標來遍歷,也可以用迭代器,但是set只能用迭代,因為他無序,無法用下標來取得想要的值。)

3、Set和List對比:
Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引起元素位置改變。
List:和數組類似,List可以動態增長,查找元素效率高,插入刪除元素效率低,因為會引起其他元素位置改變。

4、Map適合儲存鍵值對的數據

5、線程安全集合類與非線程安全集合類 :

LinkedList、ArrayList、HashSet是非線程安全的,Vector是線程安全的;
HashMap是非線程安全的,HashTable是線程安全的;
StringBuilder是非線程安全的,StringBuffer是線程安全的。

B. java中 List 與Set 有什麼區別

Java的集合類都位於java.util包中,Java集合中存放的是對象的引用,而非對象本身。

Java集合主要分為三種類型:
a.Set(集):集合中的對象不按特定方式排序,並且沒有重復對象。它的有些實現類能對集合中的對象按特定方式排序。
b.List(列表):集合中的對象按索引位置排序,可以有重復對象,允許按照對象在集合中的索引位置檢索對象。
c.Map(映射):集合中的每一個元素包含一對鍵對象和值對象,集合中沒有重復的鍵對象,值對象可以重復。它的有些實現類能對集合中的鍵對象進行排序。

Set、List和Map統稱為Java集合。

1.Set(集)
Set集合中的對象不按特定方式排序,並且沒有重復對象。Set介面主要有兩個實現類HashSet和TreeSet。HashSet類按照哈希演算法來存取集合中的對象,存取速度比較快。HashSet類還有一個子類LinkedHashSet類,它不僅實現了哈希演算法,而且實現了鏈表數據結構。TreeSet類實現了SortedSet介面,具有排序功能。

Set的add()方法判斷對象是否已經存在於集合中的判斷流程:
boolean isExists = false;
Iterator it = set.iterator();
while(it.hasNext()){
Object object = it.next();
if(newObject.equals(oldObject)){
isExists = true;
break;
}
}

2.HashSet類
當HashSet向集合中加入一個對象時,會調用對象的hashCode()方法獲得哈希碼,然後根據這個哈希碼進一步計算出對象在集合中的存放位置。

當Object1變數和object2變數實際上引用了同一個對象,那麼object1和object2的哈希碼肯定相同。

為了保證HashSet能正常工作,要求當兩個對象用equals()方法比較的結果為相等時,它們的哈希碼也相等。即:
customer1.hashCode() == customer2.hashCode();

如:對應於Customer類的以下重寫後的equals()方法:

public boolean equals(Object o){
if(this==o) return true;
if(!o instanceof Customer) return false;
final Customer other = (Customer)o;
if(this.name.equals(other.getName())&&this.age==other.getAge())
return true;
else
return false;
}

為了保證HashSet正常工作,如果Customer類覆蓋了equals()方法,也應該覆蓋hashCode()方法,並且保證兩個相等的Customer對象的哈希碼也一樣。

public int hashCode(){
int result;
result = (name==null?0:name.hashCode());
result = 29*result+(age==null?0:age.hashCode());
return result;
}

3.TreeSet類

TreeSet類實現了SortedSet介面,能夠對集合中的對象進行排序。TreeSet支持兩種排序方式:自然排序和客戶化排序,在默認情況下TreeSet採用自然排序方式。

a.自然排序
在JDK中,有一部分類實現了Comparable介面,如Integer、Double和String等。Comparable介面有一個compareTo(Object o)方法,它返回整數類型。對於表達式x.compareTo(y),如果返回值為0,表示x和y相等,如果返回值大於0,表示x大於y,如果返回值小於0,表示x小於y。

TreeSet調用對象的compareTo()方法比較集合中對象的大小,然後進行升序排列,這種排序方式稱為自然排序。

以下列出了JDK中實現了Comparable介面的一些類的排序方式
類 排序
BigDecimal\BigInteger\Byte\Double\Float\Integer\Long\Short 按數字大小排序
Character 按字元的Unicode值的數字大小排序
String 按字元串中字元的Unicode值排序

使用自然排序時,只能向TreeSet集合中加入同類型的對象,並且這些對象的類必須實現了Comparable介面,否則會在第二次調用TreeSet的add()方法時,會拋出ClassCastException異常。

例如:
以下是Customer類的compareTo()方法的一種實現方式:
public int compareTo(Object o){
Customer other = (Customer)o;

//先按照name屬性排序
if(this.name.compareTo(other.getName())>0) return 1;
if(this.name.compareTo(other.getName())<0) return -1;

//再按照age屬性排序
if(this.age>other.getAge()) return 1;
if(this.age<other.getAge()) return -1;

return 0;
}

為了保證TreeSet能正確地排序,要求Customer類的compareTo()方法與equals()方法按相同的規則比較兩個Customer對象是否相等。
因此在Customer類的equals()方法中應該採用相同的比較規則:

public boolean equals(Object o){
if(this==o) return true;
if(!(o instanceof Customer)) return false;
final Customer other = (Customer)o;

if(this.name.equals(other.getName())&&this.age==other.getAge()){
return true;
}else{
return false;
}
}

值得注意的是,對於TreeSet中已經存在的Customer對象,如果修改了它們的屬性,TreeSet不會對集合進行重新排序。在實際域模型中,實體類的屬性可以被更新,因此不適合通過TreeSet來排序。最適合於排序的是不可變類。

b.客戶化排序

除了自然排序,TreeSet還支持客戶化排序。java.util.Comparator介面用於指定具體的排序方式,它有個compare(Object object1,Object object2)方法,用於比較兩個對象的大小。當表達式compare(x,y)的值大於0,表示x大於y;當compare(x,y)的值小於0,表示x小於y;當compare(x,y)的值等於0,表示x等於y。
例如:如果希望TreeSet僅按照Customer對象的name屬性進行降序排列,可以創建一個實現Comparator介面的類CustomerComparator:

public class CustomerComparator implements Comparator{
public int compare(Object o1,Object o2){
Customer c1= (Customer)o1;
Customer c2 = (Customer)o2;

if(c1.getName().compareTo(c2.getName())>0) return -1;
if(c2.getName().compareTo(c2.getName())<0) return 1;

return 0;
}
}

接下來在構造TreeSet的實例時,調用它的TreeSet(Comparator comparator)構造方法:
Set set = new TreeSet(new CustomerComparator());

4.向Set中加入持久化類的對象

例如兩個Session實例從資料庫載入相同的Order對象,然後往HashSet集合里存放,在默認情況下,Order類的equals()方法比較兩個Orer對象的內存地址是否相同,因此order1.equals(order2)==false,所以order1和order2游離對象都加入到HashSet集合中,但實際上order1和order2對應的是ORDERS表中的同一條記錄。對於這一問題,有兩種解決方案:

(1)在應用程序中,謹慎地把來自於不同Session緩存的游離對象加入到Set集合中,如:
Set orders = new HashSet();
orders.add(order1);
if(!order2.getOrderNumber().equals(order1.getOrderNumber()))
order.add(order2);

(2)在Order類中重新實現equals()和hashCode()方法,按照業務主鍵比較兩個Order對象是否相等。

提示:為了保證HashSet正常工作,要求當一個對象加入到HashSet集合中後,它的哈希碼不會發生變化。

5.List(列表)

List的主要特徵是其對象以線性方式存儲,集合中允許存放重復對象。List介面主要的實現類有LinkedList和ArrayList。LinkedList採用鏈表數據結構,而ArrayList代表大小可變的數組。List介面還有一個實現類Vector,它的功能和ArrayList比較相似,兩者的區別在於Vector類的實現採用了同步機制,而ArrayList沒有使用同步機制。

List只能對集合中的對象按索引位置排序,如果希望對List中的對象按其他特定方式排序,可以藉助Comparator和Collections類。Collections類是集合API中的輔助類,它提供了操縱集合的各種靜態方法,其中sort()方法用於對List中的對象進行排序:
a.sort(List list):對List中的對象進行自然排序。
b.sort(List list,Comparator comparator):對List中的對象進行客戶化排序,comparator參數指定排序方式。

如Collections.sort(list);

6.Map(映射)

Map(映射)是一種把鍵對象和值對象進行映射的集合,它的每一個元素都包含一對鍵對象和值對象,而值對象仍可以是Map類型,依次類推,這樣就形成了多級映射。

Map有兩種比較常用的實現:HashMap和TreeMap。HashMap按照哈希演算法來存取鍵對象,有很好的存取性能,為了保證HashMap能正常工作,和HashSet一樣,要求當兩個鍵對象通過equals()方法比較為true時,這兩個對象的hashCode()方法返回的哈希碼也一樣。

TreeMap實現了SortedMap介面,能對鍵對象進行排序。和TreeSet一樣,TreeMap也支持自然排序和客戶化排序兩種方式。

例:創建一個緩存類EntityCache,它能粗略地模仿Session的緩存功能,保證緩存中不會出現兩個OID相同的Customer對象或兩個OID相同的Order對象,這種惟一性是由鍵對象的惟一性來保證的。

Key.java:

package mypack;

public class Key{
private Class classType;
private Long id;

public Key(Class classType,Long id){
this.classType = classType;
this.id = id;
}

public Class getClassType(){
return this.classType;
}

public Long getId(){
return this.id;
}

public boolean equals(Object o){
if(this==o) return true;
if(!(o instanceof Key)) return false;
final Key other = (Key)o;
if(classType.equals(other.getClassType())&&id.equals(other.getId()))
return true;
return false;
}

public int hashCode(){
int result;
result = classType.hashCode();
result = 29 * result + id.hashCode();
return result;
}
}

EntityCache.java:

package mypack;
import java.util.*;
public class EntityCache {
private Map entitiesByKey;
public EntityCache() {
entitiesByKey=new HashMap();
}

public void put(BusinessObject entity){
Key key=new Key(entity.getClass(),entity.getId());
entitiesByKey.put(key,entity);
}

public Object get(Class classType,Long id){
Key key=new Key(classType,id);
return entitiesByKey.get(key);
}

public Collection getAllEntities(){
return entitiesByKey.values();
}
public boolean contains(Class classType,Long id){
Key key=new Key(classType,id);
return entitiesByKey.containsKey(key);
}
}

閱讀全文

與java中list的set相關的資料

熱點內容
考駕照怎麼找伺服器 瀏覽:882
阿里雲伺服器如何更換地區 瀏覽:970
手機app調音器怎麼調古箏 瀏覽:501
銳起無盤系統在伺服器上需要設置什麼嗎 瀏覽:17
紅旗計程車app怎麼應聘 瀏覽:978
如何編寫linux程序 瀏覽:870
吉利車解壓 瀏覽:248
java輸入流字元串 瀏覽:341
安卓軟體沒網怎麼回事 瀏覽:785
dvd壓縮碟怎麼導出電腦 瀏覽:274
冒險島什麼伺服器好玩 瀏覽:541
如何在伺服器上做性能測試 瀏覽:793
命令序列錯 瀏覽:259
javaif的條件表達式 瀏覽:576
手機app上傳的照片怎麼找 瀏覽:531
雲伺服器面臨哪些威脅 瀏覽:748
c語言各種編譯特點 瀏覽:177
路由器多種加密方法 瀏覽:604
程序員阻止電腦自動彈出定位 瀏覽:168
如何做伺服器服務商 瀏覽:762