A. 在java中,什麼是集合類,跟普通類有什麼區別
簡單的說,集合類有list列,set集和map映射 三大類!
Set(集):集合中的對象無排列順序,並且沒有重復的對象.
List(隊列):集合中的對象按照索引的順序排列,可以有重復的對象。
Map(映射):集合中的每一個元素都是一對一對的,包括一個key對象,一個Value對象(一個Key指向一個Value).集合中沒有重復的key對象,但是vaulue對象可以重復.
集合類是進行集合操作的。
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);
}
}
C. Java五個最常用的集合類之間的區別和聯系
常用的集合類有一下幾種:
List結構的集合類:ArrayList類,LinkedList類,Vector類,Stack類
Map結構的集合類:HashMap類,Hashtable類
Set結構的集合類:HashSet類,TreeSet類
Queue結構的集合:Queue介面
HashMap和Hashtable的區別:
HashMap和Hashtable都是java的集合類,都可以用來存放java對象,這是他們的相同點
以下是他們的區別:
1.歷史原因:
Hashtable是基於陳舊的Dictionary類的,HashMap是java 1.2引進的Map介面的一個現實。
2.同步性:
Hashtable是同步的,這個類中的一些方法保證了Hashtable中的對象是線程安全的,而HashMap則是非同步的,因此HashMap中的對象並不是線程安全的,因為同步的要求會影響執行的效率,所以如果你不需要線程安全的結合那麼使用HashMap是一個很好的選擇,這樣可以避免由於同步帶來的不必要的性能開銷,從而提高效率,我們一般所編寫的程序都是非同步的,但如果是伺服器端的代碼除外。
3.值:
HashMap可以讓你將空值作為一個表的條目的key或value
Hashtable是不能放入空值(null)的
ArrayList和Vector的區別:
ArrayList與Vector都是java的集合類,都是用來存放java對象,這是他們的相同點,
區別:
1.同步性:
Vector是同步的,這個類的一些方法保證了Vector中的對象的線程安全的,而ArrayList則是非同步的,因此ArrayList中的對象並不 是線程安全的,因為同步要求會影響執行的效率,所以你不需要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣可以避免由於同步帶來的不必 要的性能開銷。
2.數據增長:
從內部實現的機制來講,ArrayList和Vector都是使用數組(Array)來控制集合中的對象,當你向兩種類型中增加元素的時候,如果元素的數目超過了內部數組目前的長度他們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大,所以如果你要在集合中保存大量的數據,那麼使用Vector有一些優勢,因為你可以通過設置集合的初始大小來避免不必要的資源開銷。
總結:
1)如果要求線程安全,使用Vector,Hashtable
2)如果不要求線程安全,使用ArrayList,LinkedList,HashMap
3)如果要求鍵值對,則使用HashMap,Hashtable
4)如果數據量很大,又要求線程安全考慮Vector
1.ArrayList: 元素單個,效率高,多用於查詢
2.Vector: 元素單個,線程安全,多用於查詢
3.LinkedList:元素單個,多用於插入和刪除
4.HashMap: 元素成對,元素可為空
5.HashTable: 元素成對,線程安全,元素不可為空
ArrayList
底層是Object數組,所以ArrayList具有數組的查詢速度快的優點以及增刪速度慢的缺點。
而在LinkedList的底層是一種雙向循環鏈表。在此鏈表上每一個數據節點都由三部分組成:前指針(指向前面的節點的位置),數據,後指針(指向後面的節點的位置)。最後一個節點的後指針指向第一個節點的前指針,形成一個循環。
雙向循環鏈表的查詢效率低但是增刪效率高。
ArrayList和LinkedList在用法上沒有區別,但是在功能上還是有區別的。
LinkedList
經常用在增刪操作較多而查詢操作很少的情況下:隊列和堆棧。
隊列:先進先出的數據結構。
棧:後進先出的數據結構。
注意:使用棧的時候一定不能提供方法讓不是最後一個元素的元素獲得出棧的機會。
Vector
(與ArrayList相似,區別是Vector是重量級的組件,使用使消耗的資源比較多。)
結論:在考慮並發的情況下用Vector(保證線程的安全)。
在不考慮並發的情況下用ArrayList(不能保證線程的安全)。
面試經驗(知識點):
java.util.stack(stack即為堆棧)的父類為Vector。可是stack的父類是最不應該為Vector的。因為Vector的底層是數組,且Vector有get方法(意味著它可能訪問到並不屬於最後一個位置元素的其他元素,很不安全)。
對於堆棧和隊列只能用push類和get類。
Stack類以後不要輕易使用。
實現棧一定要用LinkedList。
(在JAVA1.5中,collection有queue來實現隊列。)
Set-HashSet實現類:
遍歷一個Set的方法只有一個:迭代器(interator)。
HashSet中元素是無序的(這個無序指的是數據的添加順序和後來的排列順序不同),而且元素不可重復。
在Object中除了有finalize(),toString(),equals(),還有hashCode()。
HashSet底層用的也是數組。
當向數組中利用add(Object o)添加對象的時候,系統先找對象的hashCode:
int hc=o.hashCode(); 返回的hashCode為整數值。
Int I=hc%n;(n為數組的長度),取得余數後,利用余數向數組中相應的位置添加數據,以n為6為例,如果I=0則放在數組a[0]位置,如果I=1,則 放在數組a[1]位置。如果equals()返回的值為true,則說明數據重復。如果equals()返回的值為false,則再找其他的位置進行比 較。這樣的機制就導致兩個相同的對象有可能重復地添加到數組中,因為他們的hashCode不同。
如果我們能夠使兩個相同的對象具有相同hashcode,才能在equals()返回為真。
在實例中,定義student對象時覆蓋它的hashcode。
因為String類是自動覆蓋的,所以當比較String類的對象的時候,就不會出現有兩個相同的string對象的情況。
現在,在大部分的JDK中,都已經要求覆蓋了hashCode。
結論:如將自定義類用hashSet來添加對象,一定要覆蓋hashcode()和equals(),覆蓋的原則是保證當兩個對象hashcode返回相同的整數,而且equals()返回值為True。
如果偷懶,沒有設定equals(),就會造成返回hashCode雖然結果相同,但在程序執行的過程中會多次地調用equals(),從而影響程序執行的效率。
D. Java五個最常用的集合類之間的區別和聯系
集合類型主要有3種:set(集)、list(列表)和map(映射)。
1、List(有序、可重復)
List里存放的對象是有序的,同時也是可以重復的,List關注的是索引,擁有一系列和索引相關的方法,查詢速度快。因為往list集合里插入或刪除數據時,會伴隨著後面數段肢據的移動,所有插入刪除數據速度慢。
2、Set(無序、不能重復)
Set里存放的對象是無序,不能重復的,集合中的對象不按特定的方式排序,只是簡單地把對象加入集合中。
3、Map(鍵值對、鍵唯一、值不唯一)
Map集合中存儲的是鍵值對,鍵不能重復,值可以重復。根據鍵得到值,對map集合遍歷時先得到鍵的set集合,對set集合進行握閉世遍歷,態桐得到相應的值。
E. java list 與map有什麼區別
List:是存儲單列數據的集合,存儲的數據是有序並且是可以重復的
Map:存儲雙列數據的集合,通過鍵值對存儲數據,存儲 的數據是無序的,Key值不能重復,value值可以重復key和value是一一對應的
Collection介面
Collection是Java中最基本的集合介面。它描述了一組有關集合操作的方法。
int Size(); //集合大小
boolean isEmpty(); //是否為空
boolean contains(Object o); //是否包含某個對象
Iterator<E> iterator(); //返回一個迭代對象,用來遍歷集合中的元素
Object[] toArray(); //將集合中的元素以數組形式然後返回
<T> T[] toArray(T[] a); //上一個方法的泛型形式
boolean add(E e); //將對象e添加進集合,添加成功則返回true
boolean remove(Object o); //移除某個元素
boolean containsAll(Collection<?> c); //傳入一個集合c,如果c中的元素都存在,則返回true
boolean addAll(Collection<? extends E> c); //將集合c中的元素全部添加進本集合
boolean removeAll(Collection<?> c); //本集合減去c集合中的元素
boolean retainAll(Collection<?> c); //取本集合和c集合的交集
void clear(); //清空集合
boolean equals(Object o); //判斷相等
int hashCode(); //獲取集合當前的hash值
Set介面
Set介面直接繼承自Collection介面,並且方法介面上也一模一樣。Set對添加的元素有一些要求,其不允許出現重復的元素,並且元素之間沒有次序。這相當於一個不允許重復的離散的集合。因此,添加進Set的元素類型需要定義equals方法。若是使用自定義的類,則應該重寫equals方法來確保實現自己需要的功能。
Set介面主要實現了兩個類:HashSet,TreeSet。
HashSet是按照哈希來存取元素的,因此速度較快。HashSet繼承自抽象類AbstractSet,然後實現了Set、Cloneable、Serializable介面。
TreeSet也是繼承自AbstractSet,不過不同的是其實現的是NavigableSet介面。而NavigableSet繼承自SortedSet。SortedSet是一個有序的集合。其添加的元素必須實現了Comparable介面,因為其在添加一個元素的時候需要進行排序。NavigableSet則提供了更多的有關元素次序的方法。
LinkedHashSet也是Set的一個實現。和HashSet類似,只不過內部用鏈表來維護,按照元素插入次序來保存。
List介面
List介面也是繼承自Collection。與Set不同的是,List可以存儲重復的元素。主要有兩種實現:ArrayList和LinkedList。
ArrayList沒有什麼好說的,就像傳統的數組一樣,有著很快的隨機存取速度,但是插入刪除的速度就很慢。
LinkedList則與ArrayList恰恰相反,因為用鏈表來保存數據,所以插入刪除元素的速度很快,但是訪問數據的速度就不如ArrayList了。
Map介面
Map(映射)是一個存儲鍵值對的容器介面。每一個元素包含一個key對象和value對象,且元素不允許重復。
Map介面的實現有以下幾個:
HashMap是最常用的一個實現。HashMap使用hash映射來存取數據,這個速度是相當快,是O(1)的速度。其容量capacity,和負載因子load factor可以在一開始設定。當元素個數達到capacity*load factor的時候,就會進行擴容。
LinkedHashMap和HashMap類似,只不過內部用鏈表來維護次序。因此遍歷時候的順序是其插入順序。
TreeMap是基於紅黑樹的Map,插入的數據被有次序保存,並且有很高的效率。因此在遍歷輸出的時候可以得到排序的數據。但是這要求插入的數據實現了comparable介面。
總結
Collection、Set、List和Map都是介面,不能被實例化。
Set和List都繼承自Collection,而Map則和Collection沒什麼關系。
Set和List的區別在於Set不能重復,而List可以重復。
Map和Set與List的區別在於,Map是存取鍵值對,而另外兩個則是保存一個元素。
希望對您有所幫助!~
F. JAVA裡面set,map,list的區別是什麼(盡量詳細)
java集合的主要分為三種類型:
Set(集)
List(列表)
Map(映射)
要深入理解集合首先要了解下我們熟悉的數組:
數組是大小固定的,並且同一個數組只能存放類型一樣的數據(基本類型/引用類型),而JAVA集合可以存儲和操作數目不固定的一組數據。 所有的JAVA集合都位於 java.util包中! JAVA集合只能存放引用類型的的數據,不能存放基本數據類型。
簡單說下集合和數組的區別:(參考文章:《Thinking In Algorithm》03.數據結構之數組)
Java所有「存儲及隨機訪問一連串對象」的做法,array是最有效率的一種。
1、
效率高,但容量固定且無法動態改變。
array還有一個缺點是,無法判斷其中實際存有多少元素,length只是告訴我們array的容量。
2、Java中有一個Arrays類,專門用來操作array。
arrays中擁有一組static函數,
equals():比較兩個array是否相等。array擁有相同元素個數,且所有對應元素兩兩相等。
fill():將值填入array中。
sort():用來對array進行排序。
binarySearch():在排好序的array中尋找元素。
System.array():array的復制。
若撰寫程序時不知道究竟需要多少對象,需要在空間不足時自動擴增容量,則需要使用容器類庫,array不適用。所以就要用到集合。
那我們開始討論java中的集合。
集合分類:
Collection:List、Set
Map:HashMap、HashTable