1、介紹Collection框架的結(jié)構(gòu)
Collection FrameWork如下:Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMapCollection是最基本的集合接口,一個(gè)Collection代表一組Object,即Collection的元素(Elements)Map提供key到value的映射
2、Collection框架中實(shí)現(xiàn)比較要實(shí)現(xiàn)什么接口
comparable/comparator
3、ArrayList和Vector的區(qū)別
這兩個(gè)類都實(shí)現(xiàn)了List接口(List接口繼承了Collection接口),他們都是有序集合,即存儲(chǔ)在這兩個(gè)集合中的元素的位置都是有順序的,相當(dāng)于一種動(dòng)態(tài)的數(shù)組,我們以后可以按位置索引號(hào)取出某個(gè)元素,,并且其中的數(shù)據(jù)是允許重復(fù)的,這是HashSet之類的集合的最大不同處,HashSet之類的集合不可以按索引號(hào)去檢索其中的元素,也不允許有重復(fù)的元素(本來題目問的與hashset沒有任何關(guān)系,但為了說清楚ArrayList與Vector的功能,我們使用對(duì)比方式,更有利于說明問題)。
接著才說ArrayList與Vector的區(qū)別,這主要包括兩個(gè)方面:
(1)同步性:
Vector是線程安全的,也就是說是它的方法之間是線程同步的,而ArrayList是線程序不安全的,它的方法之間是線程不同步的。如果只有一個(gè)線程會(huì)訪問到集合,那最好是使用ArrayList,因?yàn)樗豢紤]線程安全,效率會(huì)高些;如果有多個(gè)線程會(huì)訪問到集合,那最好是使用Vector,因?yàn)椴恍枰覀冏约涸偃タ紤]和編寫線程安全的代碼。
備注:對(duì)于Vector&ArrayList、Hashtable&HashMap,要記住線程安全的問題,記住Vector與Hashtable是舊的,是java一誕生就提供了的,它們是線程安全的,ArrayList與HashMap是java2時(shí)才提供的,它們是線程不安全的。
(2)數(shù)據(jù)增長:
ArrayList與Vector都有一個(gè)初始的容量大小,當(dāng)存儲(chǔ)進(jìn)它們里面的元素的個(gè)數(shù)超過了容量時(shí),就需要增加ArrayList與Vector的存儲(chǔ)空間,每次要增加存儲(chǔ)空間時(shí),不是只增加一個(gè)存儲(chǔ)單元,而是增加多個(gè)存儲(chǔ)單元,每次增加的存儲(chǔ)單元的個(gè)數(shù)在內(nèi)存空間利用與程序效率之間要取得一定的平衡。Vector默認(rèn)增長為原來兩倍,而ArrayList的增長策略在文檔中沒有明確規(guī)定(從源代碼看到的是增長為原來的1.5倍)。ArrayList與Vector都可以設(shè)置初始的空間大小,Vector還可以設(shè)置增長的空間大小,而ArrayList沒有提供設(shè)置增長空間的方法。
總結(jié):即Vector增長原來的一倍,ArrayList增加原來的0.5倍。
4、HashMap和Hashtable的區(qū)別
(條理上還需要整理,也是先說相同點(diǎn),再說不同點(diǎn))
HashMap是Hashtable的輕量級(jí)實(shí)現(xiàn)(非線程安全的實(shí)現(xiàn)),他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全,在只有一個(gè)線程訪問的情況下,效率要高于Hashtable。
HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因?yàn)閏ontains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個(gè)實(shí)現(xiàn)。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個(gè)線程訪問Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap 就必須為之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。
就HashMap與HashTable主要從三方面來說。
一.歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是Java 1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)
二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的
三.值:只有HashMap可以讓你將空值作為一個(gè)表的條目的key或value
5、List 和 Map 區(qū)別?
一個(gè)是存儲(chǔ)單列數(shù)據(jù)的集合,另一個(gè)是存儲(chǔ)鍵和值這樣的雙列數(shù)據(jù)的集合,List中存儲(chǔ)的數(shù)據(jù)是有順序,并且允許重復(fù);Map中存儲(chǔ)的數(shù)據(jù)是沒有順序的,其鍵是不能重復(fù)的,它的值是可以有重復(fù)的。
6、List, Set, Map是否繼承自Collection接口?
List,Set是,Map不是
7、List、Map、Set三個(gè)接口,存取元素時(shí),各有什么特點(diǎn)?
這樣的題屬于隨意發(fā)揮題:這樣的題比較考水平,兩個(gè)方面的水平:一是要真正明白這些內(nèi)容,二是要有較強(qiáng)的總結(jié)和表述能力。如果你明白,但表述不清楚,在別人那里則等同于不明白。
首先,List與Set具有相似性,它們都是單列元素的集合,所以,它們有一個(gè)功共同的父接口,叫Collection。Set里面不允許有重復(fù)的元素,所謂重復(fù),即不能有兩個(gè)相等(注意,不是僅僅是相同)的對(duì)象 ,即假設(shè)Set集合中有了一個(gè)A對(duì)象,現(xiàn)在我要向Set集合再存入一個(gè)B對(duì)象,但B對(duì)象與A對(duì)象equals相等,則B對(duì)象存儲(chǔ)不進(jìn)去,所以,Set集合的add方法有一個(gè)boolean的返回值,當(dāng)集合中沒有某個(gè)元素,此時(shí)add方法可成功加入該元素時(shí),則返回true,當(dāng)集合含有與某個(gè)元素equals相等的元素時(shí),此時(shí)add方法無法加入該元素,返回結(jié)果為false。Set取元素時(shí),沒法說取第幾個(gè),只能以Iterator接口取得所有的元素,再逐一遍歷各個(gè)元素。
List表示有先后順序的集合, 注意,不是那種按年齡、按大小、按價(jià)格之類的排序。當(dāng)我們多次調(diào)用add(Obj e)方法時(shí),每次加入的對(duì)象就像火車站買票有排隊(duì)順序一樣,按先來后到的順序排序。有時(shí)候,也可以插隊(duì),即調(diào)用add(int index,Obj e)方法,就可以指定當(dāng)前對(duì)象在集合中的存放位置。一個(gè)對(duì)象可以被反復(fù)存儲(chǔ)進(jìn)List中,每調(diào)用一次add方法,這個(gè)對(duì)象就被插入進(jìn)集合中一次,其實(shí),并不是把這個(gè)對(duì)象本身存儲(chǔ)進(jìn)了集合中,而是在集合中用一個(gè)索引變量指向這個(gè)對(duì)象,當(dāng)這個(gè)對(duì)象被add多次時(shí),即相當(dāng)于集合中有多個(gè)索引指向了這個(gè)對(duì)象,如圖x所示。List除了可以以Iterator接口取得所有的元素,再逐一遍歷各個(gè)元素之外,還可以調(diào)用get(index i)來明確說明取第幾個(gè)。
Map與List和Set不同,它是雙列的集合,其中有put方法,定義如下:put(obj key,obj value),每次存儲(chǔ)時(shí),要存儲(chǔ)一對(duì)key/value,不能存儲(chǔ)重復(fù)的key,這個(gè)重復(fù)的規(guī)則也是按equals比較相等。取則可以根據(jù)key獲得相應(yīng)的value,即get(Object key)返回值為key 所對(duì)應(yīng)的value。另外,也可以獲得所有的key的結(jié)合,還可以獲得所有的value的結(jié)合,還可以獲得key和value組合成的Map.Entry對(duì)象的集合。
List 以特定次序來持有元素,可有重復(fù)元素。Set 無法擁有重復(fù)元素,內(nèi)部排序。Map 保存key-value值,value可多值。
HashSet按照hashcode值的某種運(yùn)算方式進(jìn)行存儲(chǔ),而不是直接按hashCode值的大小進(jìn)行存儲(chǔ)。例如,"abc" ---> 78,"def" ---> 62,"xyz" ---> 65在hashSet中的存儲(chǔ)順序不是62,65,78,這些問題感謝以前一個(gè)叫崔健的學(xué)員提出,最后通過查看源代碼給他解釋清楚,看本次培訓(xùn)學(xué)員當(dāng)中有多少能看懂源碼。LinkedHashSet按插入的順序存儲(chǔ),那被存儲(chǔ)對(duì)象的hashcode方法還有什么作用呢?學(xué)員想想!hashset集合比較兩個(gè)對(duì)象是否相等,首先看hashcode方法是否相等,然后看equals方法是否相等。new 兩個(gè)Student插入到HashSet中,看HashSet的size,實(shí)現(xiàn)hashcode和equals方法后再看size。
同一個(gè)對(duì)象可以在Vector中加入多次。往集合里面加元素,相當(dāng)于集合里用一根繩子連接到了目標(biāo)對(duì)象。往HashSet中卻加不了多次的。
8、說出ArrayList,Vector, LinkedList的存儲(chǔ)性能和特性
ArrayList和Vector都是使用數(shù)組方式存儲(chǔ)數(shù)據(jù),此數(shù)組元素?cái)?shù)大于實(shí)際存儲(chǔ)的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號(hào)索引元素,但是插入元素要涉及數(shù)組元素移動(dòng)等內(nèi)存操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實(shí)現(xiàn)存儲(chǔ),按序號(hào)索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但是插入數(shù)據(jù)時(shí)只需要記錄本項(xiàng)的前后項(xiàng)即可,所以插入速度較快。
LinkedList也是線程不安全的,LinkedList提供了一些方法,使得LinkedList可以被當(dāng)作堆棧和隊(duì)列來使用。
9、去掉一個(gè)Vector集合中重復(fù)的元素
Vector newVector = new Vector();
For (int i=0;i<vector.size();i++)
{
Object obj = vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
還有一種簡單的方式,HashSet set = new HashSet(vector);
10、Collection 和 Collections的區(qū)別。
Collection是集合類的上級(jí)接口,繼承與他的接口主要有Set 和List.
Collections是針對(duì)集合類的一個(gè)幫助類,他提供一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線程安全化等操作。
11、Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?
Set里的元素是不能重復(fù)的,元素重復(fù)與否是使用equals()方法進(jìn)行判斷的。
equals()和==方法決定引用值是否指向同一對(duì)象equals()在類中被覆蓋,為的是當(dāng)兩個(gè)分離的對(duì)象的內(nèi)容和類型相配的話,返回真值。
12、你所知道的集合類都有哪些?主要方法?
最常用的集合類是 List 和 Map。 List 的具體實(shí)現(xiàn)包括 ArrayList 和 Vector,它們是可變大小的列表,比較適合構(gòu)建、存儲(chǔ)和操作任何類型對(duì)象的元素列表。 List 適用于按數(shù)值索引訪問元素的情形。
Map 提供了一個(gè)更通用的元素存儲(chǔ)方法。 Map 集合類用于存儲(chǔ)元素對(duì)(稱作"鍵"和"值"),其中每個(gè)鍵映射到一個(gè)值。
ArrayList/VectorList
Collection
HashSet/TreeSetSet
PropetiesHashTable
Map
Treemap/HashMap
我記的不是方法名,而是思想,我知道它們都有增刪改查的方法,但這些方法的具體名稱,我記得不是很清楚,對(duì)于set,大概的方法是add,remove, contains;對(duì)于map,大概的方法就是put,remove,contains等,因?yàn)?,我只要在eclispe下按點(diǎn)操作符,很自然的這些方法就出來了。我記住的一些思想就是List類會(huì)有g(shù)et(int index)這樣的方法,因?yàn)樗梢园错樞蛉≡?,而set類中沒有g(shù)et(int index)這樣的方法。List和set都可以迭代出所有元素,迭代時(shí)先要得到一個(gè)iterator對(duì)象,所以,set和list類都有一個(gè)iterator方法,用于返回那個(gè)iterator對(duì)象。map可以返回三個(gè)集合,一個(gè)是返回所有的key的集合,另外一個(gè)返回的是所有value的集合,再一個(gè)返回的key和value組合成的EntrySet對(duì)象的集合,map也有g(shù)et方法,參數(shù)是key,返回值是key對(duì)應(yīng)的value。
13、兩個(gè)對(duì)象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對(duì)不對(duì)?
對(duì)。
如果對(duì)象要保存在HashSet或HashMap中,它們的equals相等,那么,它們的hashcode值就必須相等。
如果不是要保存在HashSet或HashMap,則與hashcode沒有什么關(guān)系了,這時(shí)候hashcode不等是可以的,例如arrayList存儲(chǔ)的對(duì)象就不用實(shí)現(xiàn)hashcode,當(dāng)然,我們沒有理由不實(shí)現(xiàn),通常都會(huì)去實(shí)現(xiàn)的。
14、TreeSet里面放對(duì)象,如果同時(shí)放入了父類和子類的實(shí)例對(duì)象,那比較時(shí)使用的是父類的compareTo方法,還是使用的子類的compareTo方法,還是拋異常!
(應(yīng)該是沒有針對(duì)問題的確切的答案,當(dāng)前的add方法放入的是哪個(gè)對(duì)象,就調(diào)用哪個(gè)對(duì)象的compareTo方法,至于這個(gè)compareTo方法怎么做,就看當(dāng)前這個(gè)對(duì)象的類中是如何編寫這個(gè)方法的)
實(shí)驗(yàn)代碼:
public class Parent implements Comparable {
private int age = 0;
public Parent(int age){
this.age = age;
}
public int compareTo(Object o) {
// TODO Auto-generated method stub
System.out.println("method of parent");
Parent o1 = (Parent)o;
return age>o1.age?1:age<o1.age?-1:0;
}
}
public class Child extends Parent {
public Child(){
super(3);
}
public int compareTo(Object o) {
// TODO Auto-generated method stub
System.out.println("method of child");
// Child o1 = (Child)o;
return 1;
}
}
public class TreeSetTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet set = new TreeSet();
set.add(new Parent(3));
set.add(new Child());
set.add(new Parent(4));
System.out.println(set.size());
}
}