元素的大小是固定的,並且能事先知道,用Array而不是ArrayList。java
若是能估計出存儲的元素的數目,能夠設置初始容量來避免從新計算hash值或者是擴容。程序員
爲了類型安全,可讀性和健壯性的緣由多使用泛型。同時,使用泛型還能夠避免運行時的ClassCastException。面試
使用JDK提供的不變類(immutable class)做爲Map的鍵能夠避免爲咱們本身的類實現hashCode()和equals()方法。算法
底層的集合其實是空的狀況下,返回長度是0的集合或者是數組,不要返回null。spring
每種編程語言中都有集合,最初的Java版本包含幾種集合類:Vector、Stack、HashTable和Array。隨着集合的普遍使用,Java1.2提出了囊括全部集合接口、實現和算法的集合框架。在保證線程安全的狀況下使用泛型和併發集合類,Java已經經歷了好久。它還包括在Java併發包中,阻塞接口以及它們的實現。sql
集合框架的部分優勢以下:數據庫
(1)使用核心集合類下降開發成本,而非實現咱們本身的集合類。編程
(2)隨着使用通過嚴格測試的集合框架類,代碼質量會獲得提升。設計模式
(3)經過使用JDK附帶的集合類,能夠下降代碼維護成本。數組
(4)複用性和可操做性。
Java1.5引入了泛型,全部的集合接口和實現都大量地使用它。泛型容許咱們爲集合提供一個能夠容納的對象類型,所以,若是你添加其它類型的任何元素,它會在編譯時報錯。這避免了在運行時出現ClassCastException,由於你將會在編譯時獲得報錯信息。泛型也使得代碼整潔,咱們不須要使用顯式轉換和instanceOf操做符。它也給運行時帶來好處,由於不會產生類型檢查的字節碼指令。
Collection爲集合層級的根接口。一個集合表明一組對象,這些對象即爲它的元素。Java平臺不提供這個接口任何直接的實現。
Set是一個不能包含重複元素的集合。這個接口對數學集合抽象進行建模,被用來表明集合,就如一副牌。
List是一個有序集合,能夠包含重複元素。你能夠經過它的索引來訪問任何元素。List更像長度動態變換的數組。
Map是一個將key映射到value的對象.一個Map不能包含重複的key:每一個key最多隻能映射一個value。
儘管Map接口和它的實現也是集合框架的一部分,但Map不是集合,集合也不是Map。所以,Map繼承Collection毫無心義,反之亦然。
若是Map繼承Collection接口,那麼元素去哪兒?Map包含key-value對,它提供抽取key或value列表集合的方法,可是它不適合「一組對象」規範。
(1)咱們可使用Iterator來遍歷Set和List集合,而ListIterator只能遍歷List。
(2)Iterator只能夠向前遍歷,而ListIterator能夠雙向遍歷。
(3)ListIterator從Iterator接口繼承,而後添加了一些額外的功能,好比添加一個元素、替換一個元素、獲取前面或後面元素的索引位置。
List<String> strList = new ArrayList<>(); //使用for-each循環 for(String obj : strList){ System.out.println(obj); } //using iterator Iterator<String> it = strList.iterator(); while(it.hasNext()){ String obj = it.next(); System.out.println(obj); }
使用迭代器更加線程安全,由於它能夠確保,在當前遍歷的集合元素被更改的時候,它會拋出ConcurrentModificationException。
HashMap在Map.Entry靜態內部類實現中存儲key-value對。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。當咱們經過傳遞key-value對調用put方法的時候,HashMap使用Key hashCode()和哈希算法來找出存儲key-value對的索引。Entry存儲在LinkedList中,因此若是存在entry,它使用equals()方法來檢查傳遞的key是否已經存在,若是存在,它會覆蓋value,若是不存在,它會建立一個新的entry而後保存。當咱們經過傳遞key調用get方法時,它再次使用hashCode()來找到數組中的索引,而後使用equals()方法找出正確的Entry,而後返回它的值。下面的圖片解釋了詳細內容。
其它關於HashMap比較重要的問題是容量、負荷係數和閥值調整。HashMap默認的初始容量是32,負荷係數是0.75。閥值是爲負荷係數乘以容量,不管什麼時候咱們嘗試添加一個entry,若是map的大小比閥值大的時候,HashMap會對map的內容進行從新哈希,且使用更大的容量。容量老是2的冪,因此若是你知道你須要存儲大量的key-value對,好比緩存從數據庫裏面拉取的數據,使用正確的容量和負荷係數對HashMap進行初始化是個不錯的作法。
HashMap使用Key對象的hashCode()和equals()方法去決定key-value對的索引。當咱們試着從HashMap中獲取值的時候,這些方法也會被用到。若是這些方法沒有被正確地實現,在這種狀況下,兩個不一樣Key也許會產生相同的hashCode()和equals()輸出,HashMap將會認爲它們是相同的,而後覆蓋它們,而非把它們存儲到不一樣的地方。一樣的,全部不容許存儲重複數據的集合類都使用hashCode()和equals()去查找重複,因此正確實現它們很是重要。equals()和hashCode()的實現應該遵循如下規則:
(1)若是o1.equals(o2),那麼o1.hashCode() == o2.hashCode()老是爲true的。
(2)若是o1.hashCode() == o2.hashCode(),並不意味着o1.equals(o2)會爲true。
咱們可使用任何類做爲Map的key,然而在使用它們以前,須要考慮如下幾點:
(1)若是類重寫了equals()方法,它也應該重寫hashCode()方法。
(2)類的全部實例須要遵循與equals()和hashCode()相關的規則。
(3)若是一個類沒有使用equals(),你不該該在hashCode()中使用它。
(4)用戶自定義key類的最佳實踐是使之爲不可變的,這樣,hashCode()值能夠被緩存起來,擁有更好的性能。不可變的類也能夠確保hashCode()和equals()在將來不會改變,這樣就會解決與可變相關的問題了。
Map接口提供三個集合視圖:
(1)Set keyset():返回map中包含的全部key的一個Set視圖。集合是受map支持的,map的變化會在集合中反映出來,反之亦然。當一個迭代器正在遍歷一個集合時,若map被修改了(除迭代器自身的移除操做之外),迭代器的結果會變爲未定義。集合支持經過Iterator的Remove、Set.remove、removeAll、retainAll和clear操做進行元素移除,從map中移除對應的映射。它不支持add和addAll操做。
(2)Collection values():返回一個map中包含的全部value的一個Collection視圖。這個collection受map支持的,map的變化會在collection中反映出來,反之亦然。當一個迭代器正在遍歷一個collection時,若map被修改了(除迭代器自身的移除操做之外),迭代器的結果會變爲未定義。集合支持經過Iterator的Remove、Set.remove、removeAll、retainAll和clear操做進行元素移除,從map中移除對應的映射。它不支持add和addAll操做。
(3)Set<Map.Entry<K,V>> entrySet():返回一個map鍾包含的全部映射的一個集合視圖。這個集合受map支持的,map的變化會在collection中反映出來,反之亦然。當一個迭代器正在遍歷一個集合時,若map被修改了(除迭代器自身的移除操做,以及對迭代器返回的entry進行setValue外),迭代器的結果會變爲未定義。集合支持經過Iterator的Remove、Set.remove、removeAll、retainAll和clear操做進行元素移除,從map中移除對應的映射。它不支持add和addAll操做。
對於在Map中插入、刪除和定位元素這類操做,HashMap是最好的選擇。然而,假如你須要對一個有序的key集合進行遍歷,TreeMap是更好的選擇。基於你的collection的大小,也許向HashMap中添加元素會更快,將map換爲TreeMap進行有序key的遍歷。
(1)二者都是基於索引的,內部由一個數組支持。
(2)二者維護插入的順序,咱們能夠根據插入順序來獲取元素。
(3)ArrayList和Vector的迭代器實現都是fail-fast的。
(4)ArrayList和Vector二者容許null值,也可使用索引值對元素進行隨機訪問。
(1)Vector是同步的,而ArrayList不是。然而,若是你尋求在迭代的時候對列表進行改變,你應該使用CopyOnWriteArrayList。
(2)ArrayList比Vector快,它由於有同步,不會過載。
(3)ArrayList更加通用,由於咱們可使用Collections工具類輕易地獲取同步列表和只讀列表。
Array能夠容納基本類型和對象,而ArrayList只能容納對象。
Array是指定大小的,而ArrayList大小是固定的。
Array沒有提供ArrayList那麼多功能,好比addAll、removeAll和iterator等。儘管ArrayList明顯是更好的選擇,但也有些時候Array比較好用。
ArrayList和LinkedList二者都實現了List接口,可是它們之間有些不一樣。
(1)ArrayList是由Array所支持的基於一個索引的數據結構,因此它提供對元素的隨機訪問,複雜度爲O(1),但LinkedList存儲一系列的節點數據,每一個節點都與前一個和下一個節點相鏈接。因此,儘管有使用索引獲取元素的方法,內部實現是從起始點開始遍歷,遍歷到索引的節點而後返回元素,時間複雜度爲O(n),比ArrayList要慢。
(2)與ArrayList相比,在LinkedList中插入、添加和刪除一個元素會更快,由於在一個元素被插入到中間的時候,不會涉及改變數組的大小,或更新索引。
(3)LinkedList比ArrayList消耗更多的內存,由於LinkedList中的每一個節點存儲了先後節點的引用。
ArrayList、HashMap、TreeMap和HashTable類提供對元素的隨機訪問。
Vector、HashTable、Properties和Stack是同步類,因此它們是線程安全的,能夠在多線程環境下使用。Java1.5併發API包括一些集合類,容許迭代時修改,由於它們都工做在集合的克隆上,因此它們在多線程環境中是安全的。
隊列容許先進先出(FIFO)檢索元素,但並不是老是這樣。Deque接口容許從兩端檢索元素。
棧與隊列很類似,但它容許對元素進行後進先出(LIFO)進行檢索。
Java.util.Collections是一個工具類僅包含靜態方法,它們操做或返回集合。它包含操做集合的多態算法,返回一個由指定集合支持的新集合和其它一些內容。這個類包含集合框架算法的方法,好比折半搜索、排序、混編和逆序等。
若是咱們須要對一個對象數組進行排序,咱們可使用Arrays.sort()方法。若是咱們須要排序一個對象列表,咱們可使用Collection.sort()方法。兩個類都有用於天然排序(使用Comparable)或基於標準的排序(使用Comparator)的重載方法sort()。Collections內部使用數組排序方法,全部它們二者都有相同的性能,只是Collections須要花時間將列表轉換爲數組。
在做爲參數傳遞以前,咱們可使用Collections.unmodifiableCollection(Collection c)方法建立一個只讀集合,這將確保改變集合的任何操做都會拋出UnsupportedOperationException。
經過bean 定義中的scope屬性來定義。
scope配置項有5個屬性,用於描述不一樣的做用域。
① singleton【默認】
使用該屬性定義Bean時,IOC容器僅建立一個Bean實例,IOC容器每次返回的是同一個Bean實例。
② prototype
使用該屬性定義Bean時,IOC容器能夠建立多個Bean實例,每次返回的都是一個新的實例。
③ request
該屬性僅對HTTP請求產生做用,使用該屬性定義Bean時,每次HTTP請求都會建立一個新的Bean,適用於WebApplicationContext環境。
④ session
該屬性僅用於HTTP Session,同一個Session共享一個Bean實例。不一樣Session使用不一樣的實例。
⑤ global-session
該屬性僅用於HTTP Session,同session做用域不一樣的是,全部的Session共享一個Bean實例。
編程式事務管理:這意味你經過編程的方式管理事務,給你帶來極大的靈活性,可是難維護。
聲明式事務管理:這意味着你能夠將業務代碼和事務管理分離,你只需用註解和XML配置來管理事務。
控制反轉(IOC) : 傳統應用程序是由咱們本身在對象中主動控制去直接獲取依賴對象,如今由容器幫咱們查找及注入依賴對象,對象只是被動的接受依賴對象,因此是控制反轉。
依賴注入:組件之間依賴關係由容器在運行期決定,形象的說,即由容器動態的將某個依賴關係注入到組件之中。經過依賴注入機制,咱們只須要經過簡單的配置,而無需任何代碼就可指定目標須要的資源,完成自身的業務邏輯,而不須要關心具體的資源來自何處,由誰實現。
實現方式:構造器注入、Setter方法注入、接口注入。註解裝配在默認狀況下是不開啓的,爲了使用註解裝配,咱們必須在Spring配置文件中配置 context:annotation-config/元素。
a、Bean 組件
b、Context 組件
c、Core 組件
a、用戶向服務器發送request請求,請求被SpringMVC中央控制器DispatcherServlet捕獲;
b、DispatcherServlet對請求URL進行解析,獲得請求資源標識符(URI)。而後根據該URI,調用HandlerMapping映射處理器,將請求發送給指定的Controller。
c、 Controller執行完成後,將返回的數據信息封裝到ModelAndView對象中,最後經過ViewResolver視圖解析器選擇一個合適的View 渲染視圖返回界面。
a、DEFAULT 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.
b、未提交讀(read uncommited) : 髒讀,不可重複讀,虛讀都有可能發生 。是最低的事務隔離級別,它容許另一個事務能夠看到這個事務未提交的數據。
c、已提交讀 (read commited): 避免髒讀。可是不可重複讀、虛讀有可能發生 。保證一個事物提交後才能被另一個事務讀取。另一個事務不能讀取該事物未提交的數據。Oracle 默認
d、可重複讀 (repeatable read): 這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能會出現幻象讀。它除了保證一個事務不能被另一個事務讀取未提交的數據以外還避免瞭如下狀況產生(不可重複讀)。Mysql 默認
e、串行化的 (serializable) : 這是花費最高代價、效率差但最可靠的事務隔離級別。事務被處理爲順序執行。除了防止髒讀,不可重複讀以外,還避免了幻象讀。
a、原子性 (atomicity): 一個事務中全部對數據庫的操做是一個不可分割的操做序列,要麼全作要麼全不作。
b、一致性 (consistency): 事務的執行的先後數據的完整性保持一致.
c、隔離性 (isolation): 一個事務執行的過程當中,不該該受到其餘事務的干擾
d、持久性(durability) : 一個事物一旦提交,它對數據庫的改變就是永久的
a、Propagation.REQUIRED (默認) 面試必須說出來這個。
調用方已經存在事務,則加入到同一個事務中運行,不然,自啓一個事務
b、Propagation.REQUIRES_NEW
不管什麼時候自身都會開啓新事務
c、Propagation.SUPPORTS
調用方存在事務,則加入到同一個事務中運行,若不存在事務,則以非事務的方式運行
d、Propagation.NOT_SUPPORTED
調用方存在事務,則會被掛起,直到被調用方運行完畢後,事務恢復。
e、Propagation.MANDATORY
調用方存在事務,則加入到同一個事務中運行,若不存在,則拋出異常
f、Propagation.NEVER
調用方存在事務,則拋出異常
g、Propagation.NESTED
若調用方存在事務,則運行一個嵌套事務,若調用方不存在事務,則以Propagation.REQUIRED的方式運行,即開啓一個新的事務
實例化、初始化、使用、銷燬。
靜態變量:聲明爲 static 的靜態變量實質上就是全局變量,這個靜態變量只加載一次,只分配一塊儲存空間,該類全部實例變量共用同一個 static 變量
靜態方法: 聲明爲static的靜態方法有如下幾個特色:
(1)靜態方法只能調用靜態方法;
(2)靜態方法只能訪問靜態數據;
(3)靜態方法不能以任何方式引用this或super
靜態類:一般一個普通類不容許聲明爲靜態,只有一個內部類才能夠(main方法就是一個典型),這時這個聲明的靜態類能夠直接做爲一個普通類來使用,而不須要實例一個外部類。
變量:final修飾的變量的值不能被修改,是一個常量
方法:final修飾的方法不能被重寫
類:final修飾的類不能被繼承
(1)、間接實例化方式不一樣(抽象類和接口都不能直接實例化)
實例化時,抽象類變量必須指向實現全部抽象方法的子類對象
實例化時,接口變量必須指向實現全部接口方法的類對象
(2)、繼承對象不一樣
抽象類要被子類繼承
接口要被類實現。
(3)、是否有方法實現不一樣
接口只能作方法聲明,不能有方法實現
抽象類中能夠作方法聲明,也能夠作方法實現
(4)、變量
接口裏定義的變量只能是公共的靜態的常量
抽象類中的變量是普通變量
其餘:抽象方法只能申明,不能實現。abstract void abc();不能寫成abstract void abc(){}。
抽象類裏能夠沒有抽象方法 。
若是一個類裏有抽象方法,那麼這個類只能是抽象類 。
抽象方法要被實現,因此不能是靜態的,也不能是私有的。
接口可繼承接口,並可多繼承接口,但類只能單根繼承。
(1) 能訪問除構造方法之外全部的屬性、方法,經過this.來調用方法和屬性
(2) 不能夠在靜態方法中使用
(3) 在構造方法中使用this(參數列表) 調用本類的其它構造方法,必須放在構造方法的第一句。
(1) 訪問父類的方法和屬性;
(2) 在構造方法中經過 super(參數列表) 來調用父類的構造方法,必須放在子類構造方法裏的第一行。
final:修飾符(關鍵字)有三種用法:
(1)類:若是一個類被聲明爲final,意味着它不能再派生出新的子類,即不能被繼承。
(2)變量:將變量聲明爲final,能夠保證它們在使用中不被改變,被聲明爲final 的變量在初始化之後的引用中只能讀取不可修改。
(3)方法:被聲明爲 final 的方法也一樣只能使用,不能在子類中被重寫。
finally:一般放在try…catch的後面構造老是執行代碼塊,這就意味着程序不管正常執行仍是發生異常,這裏的代碼只要JVM不關閉都能執行,能夠將釋放外部資源的代碼寫在finally塊中。
finalize:Object類中定義的方法,Java中容許使用finalize() 方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在銷燬對象時調用的,經過重寫finalize() 方法能夠整理系統資源或者執行其餘清理工做。
Error 表示系統級的錯誤和程序沒必要處理的異常,是恢復不是不可能但很困難的狀況下的一種嚴重問題;好比內存溢出,不可能期望程序能處理這樣的狀況;
Exception 表示須要捕捉或者須要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示若是程序運行正常,從不會發生的狀況。
MVC是Model—View—Controler的簡稱。即模型—視圖—控制器。MVC是一種設計模式,它強制性的把應用程序的輸入、處理和輸出分開。
MVC中的模型、視圖、控制器它們分別擔負着不一樣的任務。
模型: 模型表示業務數據和業務處理,至關於JavaBean。一個模型能爲多個視圖提供數據。這提升了應用程序的重用性。
視圖: 視圖是用戶看到並與之交互的界面。視圖向用戶顯示相關的數據,並接受用戶的輸入。視圖不進行任何業務邏輯處理。
控制器: 當用戶單擊Web頁面中的提交按鈕時,控制器接受請求並調用相應的模型去處理請求,而後根據處理的結果調用相應的視圖來顯示處理的結果。
MVC的處理過程:首先控制器接受用戶的請求,調用相應的模型來進行業務處理,並返回數據給控制器。控制器調用相應的視圖來顯示處理的結果。並經過視圖呈現給用戶。
①JDBC編程流程固定,同時將sql語句和java代碼混在了一塊兒,常常須要拼湊sql語句,細節很繁瑣;
②ibatis(mybatis)它不徹底是一個ORM框架,由於MyBatis須要程序員本身編寫Sql語句,不過mybatis能夠經過XML或註解方式靈活配置要運行的sql語句,並將java對象和sql語句映射生成最終執行的sql,最後將sql執行的結果再映射生成java對象。可是mybatis沒法作到數據庫無關性,若是須要實現支持多種數據庫的軟件則須要自定義多套sql映射文件,工做量大。
③Hibernate對象/關係映射能力強,數據庫無關性好,由於hibernate自動生成sql語句,咱們沒法控制該語句,咱們就沒法去寫特定的高效率的sql。對於一些不太複雜的sql查詢,hibernate能夠很好幫咱們完成,可是,對於特別複雜的查詢,hibernate就很難適應了,這時候用ibatis就是不錯的選擇,由於ibatis仍是由咱們本身寫sql語句。
(1)Connection提供了事務處理的方法,經過調用setAutoCommit(false)能夠設置手動提交事務;
(2)當事務完成後用commit()顯式提交事務;
(3)若是在事務處理過程當中發生異常則經過rollback()進行事務回滾。
(4)除此以外,從JDBC 3.0中還引入了Savepoint(保存點)的概念,容許經過代碼設置保存點並讓
事務回滾到指定的保存點。