第一篇:Java集合框架使用總結(jié)
前言:
本文是對(duì)Java集合框架做了一個(gè)概括性的解說(shuō),目的是對(duì)Java集合框架體系有個(gè)總體認(rèn)識(shí),如果你想學(xué)習(xí)具體的接口和類(lèi)的使用方法,請(qǐng)參看Java API文檔。
一、概述
數(shù)據(jù)結(jié)構(gòu)對(duì)程序設(shè)計(jì)有著深遠(yuǎn)的影響,在面向過(guò)程的C語(yǔ)言中,數(shù)據(jù)庫(kù)結(jié)構(gòu)用struct來(lái)描述,而在面向?qū)ο蟮木幊讨校瑪?shù)據(jù)結(jié)構(gòu)是用類(lèi)來(lái)描述的,并且包含有對(duì)該數(shù)據(jù)結(jié)構(gòu)操作的方法。
在Java語(yǔ)言中,Java語(yǔ)言的設(shè)計(jì)者對(duì)常用的數(shù)據(jù)結(jié)構(gòu)和算法做了一些規(guī)范(接口)和實(shí)現(xiàn)(具體實(shí)現(xiàn)接口的類(lèi))。所有抽象出來(lái)的數(shù)據(jù)結(jié)構(gòu)和操作(算法)統(tǒng)稱(chēng)為Java集合框架(Java Collection Framework)。
Java程序員在具體應(yīng)用時(shí),不必考慮數(shù)據(jù)結(jié)構(gòu)和算法實(shí)現(xiàn)細(xì)節(jié),只需要用這些類(lèi)創(chuàng)建出來(lái)一些對(duì)象,然后直接應(yīng)用就可以了。這樣就大大提高了編程效率。
二、集合框架的層次結(jié)構(gòu)
Collection是集合接口
|————Set子接口:無(wú)序,不允許重復(fù)。
|————List子接口:有序,可以有重復(fù)元素
區(qū)別:Collections是集合類(lèi)
Set和List對(duì)比:
Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會(huì)引起元素位置改變。
List:和數(shù)組類(lèi)似,List可以動(dòng)態(tài)增長(zhǎng),查找元素效率高,插入刪除元素效率低,因?yàn)闀?huì)引起其他元素位置改變。
Set和List具體子類(lèi):
Set
|————HashSet:以哈希表的形式存放元素,插入刪除速度很快。
List
|————ArrayList:動(dòng)態(tài)數(shù)組
|————LinkedList:鏈表、隊(duì)列、堆棧。
Array和java.util.Vector
Vector是一種老的動(dòng)態(tài)數(shù)組,是線程同步的,效率很低,一般不贊成使用。
三、Iterator迭代器(接口)
Iterator是獲取集合中元素的過(guò)程,實(shí)際上幫助獲取集合中的元素。
迭代器代替了 Java Collections Framework 中的 Enumeration。迭代器與枚舉有兩點(diǎn)不同:
迭代器允許調(diào)用方利用定義良好的語(yǔ)義在迭代期間從迭代器所指向的集合移除元素。方法名稱(chēng)得到了改進(jìn)。
Iterator僅有一個(gè)子接口ListIterator,是列表迭代器,允許程序員按任一方向遍歷列表、迭代期間修改列表,并獲得迭代器在列表中的當(dāng)前位置。ListIterator 沒(méi)有當(dāng)前元素;它的光標(biāo)位置 始終位于調(diào)用 previous()所返回的元素和調(diào)用 next()所返回的元素之間。在長(zhǎng)度為 n 的列表中,有 n+1 個(gè)有效的索引值,從 0 到 n(包含)。
四、集合框架之外的Map接口
Map將鍵映射到值的對(duì)象。一個(gè)映射不能包含重復(fù)的鍵;每個(gè)鍵最多只能映射一個(gè)值。Map接口是Dictionary(字典)抽象類(lèi)的替代品。
Map 接口提供三種collection 視圖,允許以鍵集、值集合或鍵-值映射關(guān)系集的形式查看
某個(gè)映射的內(nèi)容。映射的順序 定義為迭代器在映射的 collection 視圖中返回其元素的順序。某些映射實(shí)現(xiàn)可明確保證其順序,如 TreeMap 類(lèi);某些映射實(shí)現(xiàn)則不保證順序,如 HashMap 類(lèi)。
有兩個(gè)常見(jiàn)的已實(shí)現(xiàn)的子類(lèi):
HashMap:基于哈希表的 Map 接口的實(shí)現(xiàn)。此實(shí)現(xiàn)提供所有可選的映射操作,并允許使用 null 值和 null 鍵。(除了不同步和允許使用 null 之外,HashMap 類(lèi)與 Hashtable 大致相同。)此類(lèi)不保證映射的順序,特別是它不保證該順序恒久不變。
TreeMap:它實(shí)現(xiàn)SortedMap 接口的基于紅黑樹(shù)的實(shí)現(xiàn)。此類(lèi)保證了映射按照升序順序排列關(guān)鍵字,根據(jù)使用的構(gòu)造方法不同,可能會(huì)按照鍵的類(lèi)的自然順序 進(jìn)行排序(參見(jiàn) Comparable),或者按照創(chuàng)建時(shí)所提供的比較器進(jìn)行排序。
Hashtable:此類(lèi)實(shí)現(xiàn)一個(gè)哈希表,該哈希表將鍵映射到相應(yīng)的值。任何非 null 對(duì)象都可以用作鍵或值。
五、線程安全類(lèi)
在集合框架中,有些類(lèi)是線程安全的,這些都是JDK1.1中的出現(xiàn)的。在JDK1.2之后,就出現(xiàn)許許多多非線程安全的類(lèi)。
下面是這些線程安全的同步的類(lèi):
Vector:就比ArrayList多了個(gè)同步化機(jī)制(線程安全)。
Statck:堆棧類(lèi),先進(jìn)后出。
Hashtable:就比HashMap多了個(gè)線程安全。
Enumeration:枚舉,相當(dāng)于迭代器。
除了這些之外,其他的都是非線程安全的類(lèi)和接口。
線程安全的類(lèi)其方法是同步的,每次只能一個(gè)訪問(wèn)。是重量級(jí)對(duì)象,效率較低。對(duì)于非線程
安全的類(lèi)和接口,在多線程中需要程序員自己處理線程安全問(wèn)題。
六、其他一些接口和類(lèi)介紹
Dictionary和Hashtable類(lèi):
Dictionary提供鍵值映射的功能,是個(gè)抽象類(lèi)。一般使用它的子類(lèi)HashTable類(lèi)。遍歷Hashtable類(lèi)要用到枚舉。
Properties類(lèi)
Properties 繼承于 Hashtable,Properties 類(lèi)表示了一個(gè)持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每個(gè)鍵及其對(duì)應(yīng)值都是一個(gè)字符串。一般可以通過(guò)讀取properties配置文件來(lái)填充Properties對(duì)象。
第二篇:【java總結(jié)】集合框架
【java總結(jié)】集合框架
Collection是集合框架層次結(jié)構(gòu)中的根接口。Collection 表示一組對(duì)象,這些對(duì)象也稱(chēng)為 collection 的元素。一些 collection 允許有重復(fù)的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無(wú)序的。Collection接口下有最常用的接口為L(zhǎng)ist跟Set。需要注意的是,Map并沒(méi)有實(shí)現(xiàn)Collection接口。
List接口實(shí)現(xiàn)類(lèi)ArrayList 優(yōu)點(diǎn):類(lèi)似數(shù)組的形式進(jìn)行存儲(chǔ),因此它的隨機(jī)訪問(wèn)速度極快。缺點(diǎn):不適合于在線性表中間需要頻繁進(jìn)行插入和刪除操作。因?yàn)槊看尾迦牒蛣h除都需要移動(dòng)數(shù)組中的元素,它是用數(shù)組存儲(chǔ)元素的,這個(gè)數(shù)組可以動(dòng)態(tài)創(chuàng)建,如果元素個(gè)數(shù)超過(guò)了數(shù)組的容量,那么就創(chuàng)建一個(gè)更大的新數(shù)組,并將當(dāng)前數(shù)組中的所有元素都復(fù)制到新數(shù)組中。[html] view plain copy public class ArrayListTest {
public static void main(String[] args){
List
arrayList.add(“Welcome”);
arrayList.add(“to”);
arrayList.add(“java”);
//把ArrayList變?yōu)閿?shù)組相關(guān)的內(nèi)容進(jìn)行遍歷
String[] strArray=new String[arrayList.size()];
arrayList.toArray(strArray);
for(int i=0;i //使用迭代器進(jìn)行ArrayList遍歷 Iterator while(iter.hasNext()){ System.out.println(iter.next()); } } } List接口實(shí)現(xiàn)類(lèi)LinkedList 優(yōu)點(diǎn):適合于在鏈表中間需要頻繁進(jìn)行插入和刪除操作。 缺點(diǎn): 隨機(jī)訪問(wèn)速度較慢。查找一個(gè)元素需要從頭開(kāi)始一個(gè)一個(gè)的找。此類(lèi)實(shí)現(xiàn) Deque 接口,為 add、poll 提供先進(jìn)先出隊(duì)列操作,以及其他堆棧和雙端隊(duì)列操作LinkedList是在一個(gè)鏈表中存儲(chǔ)元素。[html] view plain copy public class LinkedListTest { public static void main(String[] args){ List //使用ForEach遍歷linkedList String[] strArray2=new String[linkedList.size()]; linkedList.toArray(strArray2); for(int i=0;i //foreach遍歷LinkedList for(String str:linkedList){ System.out.println(str); } //使用迭代器進(jìn)行ArrayList遍歷 Iterator while(iter.hasNext()){ System.out.println(iter.next()); } } } List接口實(shí)現(xiàn)類(lèi)Vector: Vector使用了關(guān)鍵字synchronized將訪問(wèn)和修改向量的方法都變成同步的了,所以對(duì)于不需要同步的應(yīng)用程序來(lái)說(shuō),類(lèi)ArrayList比類(lèi)Vector更高效。相同點(diǎn): ①都繼承于AbstractList,并且實(shí)現(xiàn)List接口 ②都實(shí)現(xiàn)了RandomAccess和Cloneable接口 ③都是通過(guò)數(shù)組實(shí)現(xiàn)的,本質(zhì)上都是動(dòng)態(tài)數(shù)組,默認(rèn)數(shù)組容量是10 ④都支持Iterator和listIterator遍歷 不同點(diǎn): ①ArrayList是非線程安全,而Vector是線程安全的 ②容量增加方式不同,Vector默認(rèn)增長(zhǎng)為原來(lái)一倍,而ArrayList卻是原來(lái)的一半+1 ③Vector支持通過(guò)Enumeration去遍歷,而List不支持 [html] view plain copy public class VectorTest { public static void main(String[] args){ Vector for(int i = 0;i < 10;i++){ vector.add(i); } //直接打印 System.out.println(vector.toString()); //size() System.out.println(vector.size()); //contains System.out.println(vector.contains(2)); //總結(jié):對(duì)比Vector的遍歷方式,使用索引的隨機(jī)訪問(wèn)方式最快,使用迭代器最慢 //iterator遍歷 Iterator while(iterator.hasNext()){ System.out.print(iterator.next()+ “ ”); } //Enumeration遍歷 Enumeration enu = vector.elements(); while(enu.hasMoreElements()){ System.out.println((Integer)enu.nextElement()); } //toArray Object[] objArr = vector.toArray(); System.out.println(“nobjArr:” + Arrays.asList(objArr)); Integer[] intArr = vector.toArray(new Integer[vector.size()]); System.out.println(“intArr:” + Arrays.asList(intArr)); //add vector.add(5); //remove vector.remove(5); System.out.println(vector); //containsAll System.out.println(vector.containsAll(Arrays.asList(5,6))); //addAll vector.addAll(Arrays.asList(555,666)); System.out.println(vector); //removeAll vector.removeAll(Arrays.asList(555,666)); System.out.println(vector); //addAll方法 vector.addAll(5, Arrays.asList(666,666, 6)); System.out.println(vector); //get方法 System.out.println(vector.get(5)); //set方法 vector.set(5, 55); System.out.println(vector.get(5)); //add方法 vector.add(0, 555); System.out.println(vector); //remove方法 vector.remove(0); System.out.println(vector); //indexof方法 System.out.println(vector.indexOf(6)); //lastIndexOf方法 System.out.println(vector.lastIndexOf(6)); //listIterator方法 ListIterator System.out.println(listIterator.hasPrevious()); //listIterator(index)方法 ListIterator System.out.println(iListIterator.previous()); //subList方法 System.out.println(vector.subList(5, 7)); //clear vector.clear(); System.out.println(vector); } } List接口實(shí)現(xiàn)類(lèi)Stack 棧類(lèi),是Java2之前引入的,繼承自類(lèi)Vector。同樣是線程同步的 [html] view plain copy public class StackTest { public static void main(String[] args){ Stack for(int i = 0;i < 10;i++){ stack.add(i); } System.out.println(stack); System.out.println(stack.peek()); stack.push(555); System.out.println(stack); System.out.println(stack.pop()); System.out.println(stack); System.out.println(stack.empty()); System.out.println(stack.search(6)); System.out.println(“stack遍歷:”); while(!stack.empty()){ System.out.print(stack.pop()+ “ ”); } } } List接口總結(jié):實(shí)際使用中我們需要根據(jù)特定的需求選用合適的類(lèi),如果 除了在末尾外不能在其他位置插入或者刪除元素,那么ArrayList效率更高,如果需要經(jīng)常插入或者刪除元素,就選擇LinkedList。 Set接口實(shí)現(xiàn)類(lèi)HashSet: HashSet是Set接口最常見(jiàn)的實(shí)現(xiàn)類(lèi),其底層是基于hash算法進(jìn)行存儲(chǔ)相關(guān)元素的。HashSet中存儲(chǔ)元素的位置是固定的(由hashCode決定),并且是無(wú)序的。Set集合中的去重和hashCode與equals方法相關(guān)。[html] view plain copy public class Num implements Comparable{ private int num; public Num(int num){ this.num=num; } @Override public int compareTo(Object o){ // TODO Auto-generated method stub Num x=(Num)o; if(num>x.num)return 1; else if(num==x.num)return 0; else return-1; } public String toString(){ return “num=”+num; } } [html] view plain copy public class HashSetTest { public static void main(String[] args){ Set hashSet.add(“hello”); hashSet.add(“world”); hashSet.add(“world”); //使用數(shù)組的方法遍歷HashSet集合String[] strArray=new String[hashSet.size()]; strArray=hashSet.toArray(strArray); for(String str:strArray){ System.out.println(str); } //使用HashSet集合直接遍歷 for(String str:hashSet){ System.out.println(str); } //用迭代器遍歷HashSet集合Iterator while(iterator.hasNext()){ System.out.println(iterator.next()); } //無(wú)重寫(xiě)hashCode跟equals方法的類(lèi),不會(huì)自動(dòng)根據(jù)類(lèi)中的值進(jìn)行去重 Set set2.add(new Num(1)); set2.add(new Num(3)); set2.add(new Num(2)); set2.add(new Num(3)); set2.add(new Num(3)); set2.add(new Num(6)); System.out.println(set2.size()); Iterator while(iterator2.hasNext()){ System.out.println(iterator2.next()); } } } Set接口實(shí)現(xiàn)類(lèi)LinkedHashSet: LinkedHashSet繼承HashSet,是用一個(gè)鏈表實(shí)現(xiàn)來(lái)擴(kuò)展HashSet類(lèi),它支持對(duì)規(guī)則集內(nèi)的元素排序。HashSet中的元素是沒(méi)有被排序的,而LinkedHashSet中的元素可以按照它們插入規(guī)則集的順序提取。[html] view plain copy public class LinkedHashSetTest { public static void main(String[] args){ Set linkedHashSet.add(“hello”); linkedHashSet.add(“world”); linkedHashSet.add(“world”); //使用數(shù)組的方法遍歷HashSet集合String[] strArray=new String[linkedHashSet.size()]; strArray=linkedHashSet.toArray(strArray); for(String str:strArray){ System.out.println(str); } //使用HashSet集合直接遍歷 for(String str:linkedHashSet){ System.out.println(str); } //用迭代器遍歷HashSet集合Iterator while(iterawww.tmdps.cntor.hasNext()){ System.out.println(iterator.next()); } } } Set接口實(shí)現(xiàn)類(lèi)TreeSet: TreeSet實(shí)現(xiàn)了Set接口,它與HashSet的區(qū)別主要在于TreeSet中的元素會(huì)按照相關(guān)的值進(jìn)行排序。HashSet是通過(guò)HashMap實(shí)現(xiàn)的,TreeSet是通過(guò)TreeMap實(shí)現(xiàn)的,只不過(guò)Set用的只是Map的key。由于TreeMap需要排序,所以需要一個(gè)Comparator為鍵值進(jìn)行大小比較.當(dāng)然也是用Comparator定位的.如果創(chuàng)建時(shí)沒(méi)有確定,那么就會(huì)使用key.compareTo()方法,這就要求key必須實(shí)現(xiàn)Comparable接口.TreeMap是使用Tree數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,所以使用compare接口就可以完成定位了.注意:TreeSet是根據(jù)對(duì)象的CompareTo方法來(lái)去重的,如果CompaerTo返回0說(shuō)明兩個(gè)對(duì)象相等,不能同時(shí)存在于TreeSet中。 [html] view plain copy public class TreeSetTest { public static void main(String[] args){ Set treeSet.add(“d”); treeSet.add(“c”); treeSet.add(“b”); treeSet.add(“a”); //String實(shí)體類(lèi)中實(shí)現(xiàn)Comparable接口,所以在初始化TreeSet的時(shí)候, //無(wú)需傳入比較器 Iterator while(iterator.hasNext()){ System.out.println(iterator.next()); } Set treeSet2.add(new Num(1)); treeSet2.add(new Num(3)); treeSet2.add(new Num(2)); treeSet2.add(new Num(3)); treeSet2.add(new Num(3)); treeSet2.add(new Num(6)); System.out.println(treeSet2.size()); Iterator while(iterator2.hasNext()) { System.out.println(iterator2.next()); } TreeSet set.add(1111); set.add(2222); set.add(3333); set.add(4444); set.add(5555); System.out.println(set.first());// 輸出第一個(gè)元素 System.out.println(set.lower(3333));//小于3333的最大元素 System.out.println(set.higher(2222));//大于2222的最大元素 System.out.println(set.floor(3333));//不大于3333的最大元素 System.out.println(set.ceiling(3333));//不小于3333的最大元素 System.out.println(set.pollFirst());//刪除第一個(gè)元素 System.out.println(set.pollLast());//刪除最后一個(gè)元素 System.out.println(set); } } Set接口區(qū)別于List接口在于: 所有Set中的元素實(shí)現(xiàn)了不重復(fù),有點(diǎn)像數(shù)學(xué)中集合的概念,無(wú)序,不允許有重復(fù)的元素,最多允許有一個(gè)null元素對(duì)象 Map接口: Map接口儲(chǔ)存一組成對(duì)的鍵-值對(duì)象,提供key(鍵)到value(值)的映射,Map中的key不要求有序,不允許重復(fù)。value同樣不要求有序,但可以重復(fù)。 Map實(shí)現(xiàn)類(lèi)HashMap 最常見(jiàn)的Map實(shí)現(xiàn)類(lèi),他的儲(chǔ)存方式是哈希表,優(yōu)點(diǎn)是查詢指定元素效率高。HashMap采用數(shù)組+鏈表實(shí)現(xiàn),即使用鏈表處理沖突,同一hash值的鏈表都存儲(chǔ)在一個(gè)鏈表里。但是當(dāng)鏈表中的元素較多,即hash值相等的元素較多時(shí),通過(guò)key值依次查找的效率較低。而JDK1.8中,HashMap采用數(shù)組+鏈表+紅黑樹(shù)實(shí)現(xiàn),當(dāng)鏈表長(zhǎng)度超過(guò)閾值(8)時(shí),將鏈表轉(zhuǎn)換為紅黑樹(shù),這樣大大減少了查找時(shí)間。 無(wú)論什么情況HashMap中哈希表的容量總是2的n次方的一個(gè)數(shù)。并且有這樣一個(gè)公式:當(dāng)length=2^n時(shí),hashcode &(length-1)== hashcode % length HashMap與Hashtable的區(qū)別: Hashtable實(shí)現(xiàn)Map接口,繼承自古老的Dictionary類(lèi),實(shí)現(xiàn)一個(gè)key-value的鍵值映射表。任何非空的(key-value)均可以放入其中。區(qū)別主要有三點(diǎn): 1.Hashtable是基于陳舊的Dictionary實(shí)現(xiàn)的,而HashMap是基于Java1.2引進(jìn)的Map接口實(shí)現(xiàn)的; 2.Hashtable是線程安全的,而HashMap是非線程安全的,我們可以使用外部同步的方法解決這個(gè)問(wèn)題。 3.HashMap可以允許你在列表中放一個(gè)key值為null的元素,并且可以有任意多value為null,而Hashtable不允許鍵或者值為null。 [html] view plain copy public class HashMapTest { public static void main(String[] args){ Map hashMap.put(“a”,1); hashMap.put(“b”,2); hashMap.put(“JAVA”,3); System.out.println(hashMap.get(“JAVA”)); //第一種遍歷方法:普遍使用,二次取值 for(String key : hashMap.keySet()){ System.out.println(“key= ”+ key + “ and value= ” + hashMap.get(key)); } //第二種:通過(guò)Map.entrySet使用iterator遍歷key和value Iterator while(iter.hasNext()){ System.out.println(iter.next()); } //第三種:通過(guò)Map.entrySet遍歷key和value.推薦,尤其是容量大時(shí) for(Map.Entry System.out.println(“key= ” + entry.getKey()+ “ and value= ” + entry.getValue()); } //第四種:通過(guò)Map.values()遍歷所有的value,但不能遍歷key for(Integer v : hashMap.values()){ System.out.println(“value= ” + v); } } } Map實(shí)現(xiàn)類(lèi)LinkedHashMap LinkedHashMap繼承自HashMap,它主要是用鏈表實(shí)現(xiàn)來(lái)擴(kuò)展HashMap類(lèi),HshMap中條目是沒(méi)有順序的,但是在LinkedHashMap中元素既可以按照它們插入圖的順序排序,也可以按它們最后一次被訪問(wèn) 的順序排序。LinkedHashMap繼承自HashMap并且實(shí)現(xiàn)了Map接口。和HashMap一樣,LinkedHashMap 允許key和value均為null。于該數(shù)據(jù)結(jié)構(gòu)和HashMap一樣使用到hash算法,因此它不能保證映射的順序,尤其是不能保證順序持久不變(再哈希)。 [html] view plain copy public class LinkedHashMapTest { public static void main(String[] args){ Map linkedHashMap.put(“a”, 1); linkedHashMap.put(“java”,2); linkedHashMap.put(“C”, 3); System.out.println(linkedHashMap.get(“a”)); Set Iterator while(iter.haswww.tmdps.cnn(String[] args){ Map treeMap.put(“b”,2); treeMap.put(“a”,1); treeMap.put(“e”,5); treeMap.put(“d”,4); treeMap.put(“c”,3); Set Iterator while(iter.hasNext()){ System.out.println(iter.next()); } Set for(String x:keySet){ System.out.println(x+“=”+treeMap.get(x)); } Map treeMap2.put(new Num(2),“a”); treeMap2.put(new Num(1),“b”); treeMap2.put(new Num(5),“c”); treeMap2.put(new Num(4),“d”); treeMap2.put(new Num(3),“c”); Set for(Num x:kewww.tmdps.cnySet2){ System.out.println(x+“=”+treeMap2.get(x)); } //根據(jù)value排序 Map map.put(“d”, 2); map.put(“c”, 1); map.put(“b”, 4); map.put(“a”, 3); List new ArrayList //排序前 for(int i = 0;i < infoIds.size();i++){ String id = infoIds.get(i).toString(); System.out.println(id); } //排序 Collections.sort(infoIds, new Comparator public int compare(Map.Entry return(o2.getValue()-o1.getValue()); //return(o1.getKey()).toString().compareTo(o2.getKey()); } }); //排序后 for(int i = 0;i < infoIds.size();i++){ String id = infoIds.get(i).toString(); System.out.println(id); } } } Map接口總結(jié):在實(shí)際使用中,如果更新圖時(shí)不需要保持圖中元素的順序,就使用HashMap,如果需要保持圖中元素的插入順序或者訪問(wèn)順序,就使用LinkedHashMap,如果需要使圖按照鍵值排序,就使用TreeMap。 Java集合框架是最常被問(wèn)到的Java面試問(wèn)題,要理解Java技術(shù)強(qiáng)大特性,就有必要掌握集合框架。這里有一些實(shí)用問(wèn)題,常在Java面試中問(wèn)到。 1、什么是Java集合API Java集合框架API是用來(lái)表示和操作集合的統(tǒng)一框架,它包含接口、實(shí)現(xiàn)類(lèi)、以及幫助程序員完成一些編程的算法。簡(jiǎn)言之,API在上層完成以下幾件事: ● 編程更加省力,提高城程序速度和代碼質(zhì)量 ● 非關(guān)聯(lián)的API提高互操作性 ● 節(jié)省學(xué)習(xí)使用新API成本 ● 節(jié)省設(shè)計(jì)新API的時(shí)間 ● 鼓勵(lì)、促進(jìn)軟件重用 具體來(lái)說(shuō),有6個(gè)集合接口,最基本的是Collection接口,由三個(gè)接口Set、List、SortedSet繼承,另外兩個(gè)接口是Map、SortedMap,這兩個(gè)接口不繼承Collection,表示映射而不是真正的集合。 2、什么是Iterator 一些集合類(lèi)提供了內(nèi)容遍歷的功能,通過(guò)java.util.Iterator接口。這些接口允許遍歷對(duì)象的集合。依次操作每個(gè)元素對(duì)象。當(dāng)使用Iterators時(shí),在獲得Iterator的時(shí)候包含一個(gè)集合快照。通常在遍歷一個(gè)Iterator的時(shí)候不建議修改集合本省。 3、Iterator與ListIterator有什么區(qū)別? Iterator:只能正向遍歷集合,適用于獲取移除元素。ListIerator:繼承Iterator,可以雙向列表的遍歷,同樣支持元素的修改。 4、什么是HaspMap和Map? Map是接口,Java 集合框架中一部分,用于存儲(chǔ)鍵值對(duì),HashMap是用哈希算法實(shí)現(xiàn)Map的類(lèi)。 5、HashMap與HashTable有什么區(qū)別?對(duì)比Hashtable VS HashMap 兩者都是用key-value方式獲取數(shù)據(jù)。Hashtable是原始集合類(lèi)之一(也稱(chēng)作遺留類(lèi))。HashMap作為新集合框架的一部分在Java2的1.2版本中加入。它們之間有一下區(qū)別: ● HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允許null值作為key和value,而Hashtable不可以)。 ● HashMap沒(méi)法保證映射的順序一直不變,但是作為HashMap的子類(lèi)LinkedHashMap,如果想要預(yù)知的順序迭代(默認(rèn)按照插入順序),你可以很輕易的置換為HashMap,如果使用Hashtable就沒(méi)那么容易了。 ● HashMap不是同步的,而Hashtable是同步的。 ● 迭代HashMap采用快速失敗機(jī)制,而Hashtable不是,所以這是設(shè)計(jì)的考慮點(diǎn)。 6、在Hashtable上下文中同步是什么意思? 同步意味著在一個(gè)時(shí)間點(diǎn)只能有一個(gè)線程可以修改哈希表,任何線程在執(zhí)行hashtable的更新操作前需要獲取對(duì)象鎖,其他線程等待鎖的釋放。 7、什么叫做快速失敗特性 從高級(jí)別層次來(lái)說(shuō)快速失敗是一個(gè)系統(tǒng)或軟件對(duì)于其故障做出的響應(yīng)。一個(gè)快速失敗系統(tǒng)設(shè)計(jì)用來(lái)即時(shí)報(bào)告可能會(huì)導(dǎo)致失敗的任何故障情況,它通常用來(lái)停止正常的操作而不是嘗試?yán)^續(xù)做可能有缺陷的工作。當(dāng)有問(wèn)題發(fā)生時(shí),快速失敗系統(tǒng)即時(shí)可見(jiàn)地發(fā)錯(cuò)錯(cuò)誤告警。在Java中,快速失敗與iterators有關(guān)。如果一個(gè)iterator在集合對(duì)象上創(chuàng)建了,其它線程欲“結(jié)構(gòu)化”的修改該集合對(duì)象,并發(fā)修改異常(ConcurrentModificationException)拋出。 8、怎樣使Hashmap同步? HashMap可以通過(guò)Map m = Collections.synchronizedMap(hashMap)來(lái)達(dá)到同步的效果。 9、什么時(shí)候使用Hashtable,什么時(shí)候使用HashMap 基本的不同點(diǎn)是Hashtable同步HashMap不是的,所以無(wú)論什么時(shí)候有多個(gè)線程訪問(wèn)相同實(shí)例的可能時(shí),就應(yīng)該使用Hashtable,反之使用HashMap。非線程安全的數(shù)據(jù)結(jié)構(gòu)能帶來(lái)更好的性能。 如果在將來(lái)有一種可能—你需要按順序獲得鍵值對(duì)的方案時(shí),HashMap是一個(gè)很好的選擇,因?yàn)橛蠬ashMap的一個(gè)子類(lèi)LinkedHashMap。所以如果你想可預(yù)測(cè)的按順序迭代(默認(rèn)按插入的順序),你可以很方便用LinkedHashMap替換HashMap。反觀要是使用的Hashtable就沒(méi)那么簡(jiǎn)單了。同時(shí)如果有多個(gè)線程訪問(wèn)HashMap,Collections.synchronizedMap()可以代替,總的來(lái)說(shuō)HashMap更靈活。 10、為什么Vector類(lèi)認(rèn)為是廢棄的或者是非官方地不推薦使用?或者說(shuō)為什么我們應(yīng)該一直使用ArrayList而不是Vector 你應(yīng)該使用ArrayList而不是Vector是因?yàn)槟J(rèn)情況下你是非同步訪問(wèn)的,Vector同步了每個(gè)方法,你幾乎從不要那樣做,通常有想要同步的是整個(gè)操作序列。同步單個(gè)的操作也不安全(如果你迭代一個(gè)Vector,你還是要加鎖,以避免其它線程在同一時(shí)刻改變集合).而且效率更慢。當(dāng)然同樣有鎖的開(kāi)銷(xiāo)即使你不需要,這是個(gè)很糟糕的方法在默認(rèn)情況下同步訪問(wèn)。你可以一直使用Collections.sychronizedList來(lái)裝飾一個(gè)集合。 事實(shí)上Vector結(jié)合了“可變數(shù)組”的集合和同步每個(gè)操作的實(shí)現(xiàn)。這是另外一個(gè)設(shè)計(jì)上的缺陷。Vector還有些遺留的方法在枚舉和元素獲取的方法,這些方法不同于List接口,如果這些方法在代碼中程序員更趨向于想用它。盡管枚舉速度更快,但是他們不能檢查如果集合在迭代的時(shí)候修改了,這樣將導(dǎo)致問(wèn)題。盡管以上諸多原因,oracle也從沒(méi)宣稱(chēng)過(guò)要廢棄Vector. 對(duì)于java中SSH框架的理解 SSH 是指 Struts+ spring+ hibernate 的一個(gè)集成框架,這是一種比較流行的java web應(yīng)用程序開(kāi)源框架。 Struts Struts是一個(gè)基于Sun J2EE平臺(tái)的MVC框架,主要采用Servlet和JSP技術(shù)來(lái)實(shí)現(xiàn)的。由于Struts能充分滿足引用開(kāi)發(fā)的需求,簡(jiǎn)單易用,敏捷迅速,所以很受關(guān)注。Struts 吧Servlet、JSP、自定義標(biāo)簽和信息資源(message resource)整合到一個(gè)統(tǒng)一的框架中,開(kāi)發(fā)人員利用其進(jìn)行開(kāi)發(fā)室不用再自己編寫(xiě)實(shí)現(xiàn)全套的MVC模式,極大的節(jié)省了時(shí)間。 Spring Spring是一個(gè)解決了許多在J2EE開(kāi)發(fā)中常見(jiàn)的問(wèn)題的強(qiáng)大框架。Spring提供了管理業(yè)務(wù)對(duì)象的一致方法并且鼓勵(lì)了注入對(duì)接口編程而不是對(duì)類(lèi)編程的良好習(xí)慣。 Spring的架構(gòu)基礎(chǔ)是基于JavaBean屬性的Inversion of Control 容器。然而,這僅僅是完整圖景中的一部分:在Spring使用IOC容器作為構(gòu)建完關(guān)注所有架構(gòu)層的完整解決方案是獨(dú)一無(wú)二的。Spring提供了唯一的數(shù)據(jù)訪問(wèn)抽象,包括簡(jiǎn)單和有效率的JDBC框架,極大的改進(jìn)了效率并且減少了可能的錯(cuò)誤。Spring的數(shù)據(jù)訪問(wèn)架構(gòu)還集成了Hibernate 和其他O/R mapping 解決方案。Spring還提供了唯一的事物管理抽象。它能夠在各種底層事務(wù)管理技術(shù),例如JTA 或者JDBC事務(wù)提供一個(gè)一致的編程模型。Spring提供了一個(gè)標(biāo)準(zhǔn)Java語(yǔ)言編寫(xiě)的AOP框架,他給POJOs提供了聲明式的事務(wù)管理和其他企業(yè)事務(wù)——如果有必要還可以實(shí)現(xiàn)自己的aspects。這個(gè)框架提供了可以和IOC容器集成的強(qiáng)大而靈活的MVC web框架。 Hibernate Hibernate 是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝,是的java程序員可以隨心所欲的適用對(duì)象編程思維來(lái)操控?cái)?shù)據(jù)庫(kù)。Hibernate 可以應(yīng)用在任何使用JDBC的場(chǎng)合,既可以在java客戶端程序中使用,也可以在Servlet/jsp的web應(yīng)用中使用,其最具革命性意義的是:Hibernate可以在應(yīng)用EJB的J2EE架構(gòu)中取代CMP,完成數(shù)據(jù)持久化的重任。 在SSH的組合框架模式中,三者各自的作用 Struts 是一個(gè)很好的MVC框架,主要技術(shù)是Servlet和JSP。Struts的MVC設(shè)計(jì)模式可以讓我們的邏輯思維變得很清晰,讓我們寫(xiě)程序?qū)哟畏置鳌?/p> Spring提供了管理業(yè)務(wù)對(duì)象的一致方法,并鼓勵(lì)注入對(duì)接口編程而不是對(duì)類(lèi)編程的良好習(xí)慣,使我們的產(chǎn)品在最大程度上解耦。 Hibernate 是用來(lái)持久化數(shù)據(jù)的,提供了完全面向?qū)ο蟮臄?shù)據(jù)庫(kù)操作。Hibernate對(duì)JDBC進(jìn)行了非常輕量級(jí)的封裝,使得他與關(guān)系型數(shù)據(jù)庫(kù)打交道變得非常輕松。 負(fù)責(zé)Web層: ActionFormBean接收網(wǎng)頁(yè)中表單提交的數(shù)據(jù),然后通過(guò)Action進(jìn)行處理,再Forward到對(duì)應(yīng)的網(wǎng)頁(yè),在Struts-config.xml中定義了 Spring負(fù)責(zé)業(yè)務(wù)層管理,即Service: Service為Action提供統(tǒng)一的調(diào)用接口,封裝持久層的DAO,并集成Hibernate,Spring可對(duì)JavaBean和事物進(jìn)行統(tǒng)一管理。 Hibernate負(fù)責(zé)持久層,完成數(shù)據(jù)庫(kù)的CRUD操作: Hibernate有一組hbm.xml文件和PO,是與數(shù)據(jù)庫(kù)中的表相對(duì)應(yīng)的,然后定義DAO,這些是與數(shù)據(jù)庫(kù)打交道的類(lèi)。 在Struts+Spring+Hibernate系統(tǒng)中,對(duì)象之間的調(diào)用流程如下: Struts——>Spring——>Hibernate JSP——>Action——>Service——>DAO——>Hibernate Java Web框架簡(jiǎn)介 Web框架是人們?cè)谑褂媚撤N語(yǔ)言編寫(xiě)Web應(yīng)用服務(wù)端時(shí)關(guān)于架構(gòu)的最佳實(shí)踐。 有些Web框架是從實(shí)際的Web項(xiàng)目抽取出來(lái)的,也就是說(shuō),做一個(gè)具體的應(yīng)用項(xiàng)目時(shí),采取的架構(gòu)比較理想,就把這部分和領(lǐng)域無(wú)關(guān),而僅和Web的請(qǐng)求和響應(yīng)處理有關(guān)的設(shè)計(jì)拿出來(lái),形成一個(gè)基礎(chǔ),在開(kāi)發(fā)別的應(yīng)用項(xiàng)目的時(shí)候則可以從這基礎(chǔ)做起,讓開(kāi)發(fā)者更關(guān)注領(lǐng)域問(wèn)題,而不是Web的請(qǐng)求和響應(yīng)的控制。 也有些Web框架是直接設(shè)計(jì)出來(lái)的,很多Web框架在設(shè)計(jì)的時(shí)候也都借鑒了別的框架,吸取優(yōu)點(diǎn),修改不足,并根據(jù)自己的框架的定位,在特定方面有自己的發(fā)揮,形成了自己的特點(diǎn),比如有的web框架追求的是松耦合性,層次,結(jié)構(gòu)之間都不密切綁定,有的Web框架則追求敏捷性,強(qiáng)調(diào)約定而不是配置。 Java 的 Web框架雖然各不相同,但基本也都是遵循特定的路數(shù)的:使用Servlet或者Filter攔截請(qǐng)求,使用MVC的思想設(shè)計(jì)架構(gòu),使用約定,XML或 Annotation實(shí)現(xiàn)配置,運(yùn)用Java面向?qū)ο蟮奶攸c(diǎn),面向抽象實(shí)現(xiàn)請(qǐng)求和響應(yīng)的流程,支持Jsp,F(xiàn)reemarker,Velocity等視圖。 JSF 優(yōu)點(diǎn): Java EE標(biāo)準(zhǔn),這意味著有很大的市場(chǎng)需求和更多的工作機(jī)會(huì) 上手快速并且相對(duì)容易 有大量可用的組件庫(kù) 缺點(diǎn): 大量的JSP標(biāo)簽 對(duì)REST和安全支持不好 沒(méi)有一個(gè)統(tǒng)一的實(shí)現(xiàn)。既有SUN的實(shí)現(xiàn),又有Apache的實(shí)現(xiàn)——MyFaces。 國(guó)內(nèi)的OperaMasks還支持AJAX,以及有開(kāi)發(fā)工具支持 Spring MVC 優(yōu)點(diǎn): 對(duì)覆蓋綁定(overriding binding)、驗(yàn)證(validation)等提供生命周期管理 與許多表示層技術(shù)/框架無(wú)縫集成:JSP/JSTL、Tiles、Velocity、FreeMarker、Excel、XSL、PDF 等 便于測(cè)試——?dú)w功于IoC 缺點(diǎn): 大量的XML配置文件 太過(guò)靈活——沒(méi)有公共的父控制器 沒(méi)有內(nèi)置的Ajax支持 Stripes 優(yōu)點(diǎn): 不需要書(shū)寫(xiě)XML配置文件 良好的學(xué)習(xí)文檔 社區(qū)成員很熱心 缺點(diǎn): 社區(qū)比較小 不如其他的項(xiàng)目活躍 ActionBean里面的URL是硬編碼的 Struts 2 優(yōu)點(diǎn): 架構(gòu)簡(jiǎn)單——易于擴(kuò)展 標(biāo)記庫(kù)很容易利用FreeMarker或者Velocity來(lái)定制 基于控制器或者基于頁(yè)面的導(dǎo)航 缺點(diǎn): 文檔組織得很差 對(duì)新特征過(guò)分關(guān)注 通過(guò)Google搜索到的大多是Struts 1.x的文檔 Tapestry 優(yōu)點(diǎn): 一旦學(xué)會(huì)它,將極大地提高生產(chǎn)率 HTML模板——對(duì)頁(yè)面設(shè)計(jì)師非常有利 每出一個(gè)新版本,都會(huì)有大量的創(chuàng)新 缺點(diǎn): 文檔過(guò)于概念性,不夠?qū)嵱?/p> 學(xué)習(xí)曲線陡峭 發(fā)行周期長(zhǎng)——每年都有較大的升級(jí) Wicket 優(yōu)點(diǎn): 對(duì)Java開(kāi)發(fā)者有利(不是Web開(kāi)發(fā)者) 頁(yè)面和顯示綁定緊密 社區(qū)活躍——有來(lái)自創(chuàng)建者的支持 缺點(diǎn): HTML模板和Java代碼緊挨著 需要對(duì)OO有較好的理解 Wicket邏輯——什么都用Java搞定第三篇:Java程序員集合框架面試題
第四篇:java的SSH框架總結(jié)(范文)
第五篇:java web框架簡(jiǎn)介