是最基本的接口,派生了兩個子接口Set和List前端
無序且不可重複java
基於HashMap實現,全部元素都是保存在HashMap的key中,而value中保存了PRESENT。程序員
有序且可重複web
總結:面試
Map也是接口,但沒有繼承Collection接口。該接口描述了從不重複的鍵到值的映射。Map接口用於維護鍵/值對算法
基於哈希表實現,特色就是鍵值對的映射關係。一個key對應一個Value。HashMap中元素的排列順序是不固定的。更加適合於對元素進行插入、刪除和定位。spring
HashMap和Hashtable都實現了Map接口,但決定用哪個以前先要弄清楚它們之間的分別。主要的區別有:線程安全性,同步(synchronization),以及速度。sql
Map m = Collections.synchronizeMap(hashMap);數據庫
基於紅黑樹實現。TreeMap中的元素保持着某種固定的順序。更加適合於對元素的順序遍歷。編程
迭代器是一種模式,它可使得對於序列類型的數據結構的遍歷行爲與被遍歷的對象分離
Iterator對集合類中的任何一個實現類,均可以返回這樣一個Iterator對象。能夠適用於任何一個類。
由於集合類(List和Set等)能夠裝入的對象的類型是不肯定的,從集合中取出時都是Object類型,用時都須要進行強制轉化,這樣會很麻煩,用上泛型,就是提早告訴集合肯定要裝入集合的類型,這樣就能夠直接使用而不用顯示類型轉換.很是方便.
優點在於更加簡潔,更不容易出錯,沒必要關心下標的起始值和終止值
forEach不是關鍵字,關鍵字仍是for,語句是由iterator實現的,他們最大的不一樣之處就在於remove()方法上
若是在循環的過程當中調用集合的remove()方法,就會致使循環出錯,由於循環過程當中list.size()的大小變化了,就致使了錯誤。 因此,若是想在循環語句中刪除集合中的某個元素,就要用迭代器iterator的remove()方法,由於它的remove()方法不只會刪除元素,還會維護一個標誌,用來記錄目前是否是可刪除狀態,例如,你不能連續兩次調用它的remove()方法,調用以前至少有一次next()方法的調用。
簡單地說,就是一個變量和常量的關係。StringBuffer對象的內容能夠修改;而String對象一旦產生後就不能夠被修改,從新賦值實際上是兩個對象
在String類中沒有用來改變已有字符串中的某個字符的方法,因爲不能改變一個Java字符串中的某個單獨字符,因此在JDK文檔中稱String類的對象是不可改變的。然而,不可改變的字符串具備一個很大的優勢:編譯器能夠把字符串設爲共享的。
是對象不是原始類型.
爲不可變對象,一旦被建立,就不能修改它的值.
對於已經存在的String對象的修改都是從新建立一個新的對象,而後把新的值保存進去.
String 是final類,即不能被繼承.
是一個可變對象,當對他進行修改的時候不會像String那樣從新創建對象
它只能經過構造函數來創建,
StringBuffer sb = new StringBuffer();
注意:不能經過賦值符號對他進行賦值.
sb = "welcome to here!";//error
對象被創建之後,在內存中就會分配內存空間,並初始保存一個null.向StringBuffer
中賦值的時候能夠經過它的append方法.
sb.append("hello");
可預先分配指定長度的內存塊創建一個字符串緩衝區。這樣使用StringBuffer類的append方法追加字符 比 String使用 + 操做符添加字符 到 一個已經存在的字符串後面有效率得多。由於使用 + 操做符每一次將字符添加到一個字符串中去時,字符串對象都須要尋找一個新的內存空間來容納更大的字符串,這無凝是一個很是消耗時間的操做。添加多個字符也就意味着要一次又一次的對字符串從新分配內存。使用StringBuffer類就避免了這個問題。
進程:每一個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較大的開銷,一個進程包含1--n個線程。
線程:同一類線程共享代碼和數據空間,每一個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小。
線程和進程同樣分爲五個階段:建立、就緒、運行、阻塞、終止。
多進程是指操做系統能同時運行多個任務(程序)。
多線程是指在同一程序中有多個順序流在執行。
新建狀態(New):當線程對象對建立後,即進入了新建狀態,如:Thread t = new MyThread();
就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經作好了準備,隨時等待CPU調度執行,並非說執行了t.start()此線程當即就會執行;
運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就 緒狀態是進入到運行狀態的惟一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中;
阻塞狀態(Blocked):處於運行狀態中的線程因爲某種緣由,暫時放棄對CPU的使用權,中止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的緣由不一樣,阻塞狀態又能夠分爲三種:
1.等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;
2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(由於鎖被其它線程所佔用),它會進入同步阻塞狀態;
3.其餘阻塞 -- 經過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入就緒狀態。
死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
一種是繼承Thread類,另一種是實現Runable接口
class MyThread extends Thread { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } }
public class ThreadTest { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { Thread myThread1 = new MyThread(); // 建立一個新的線程 myThread1 此線程進入新建狀態 Thread myThread2 = new MyThread(); // 建立一個新的線程 myThread2 此線程進入新建狀態 myThread1.start(); // 調用start()方法使得線程進入就緒狀態 myThread2.start(); // 調用start()方法使得線程進入就緒狀態 } } } }
繼承Thread類,經過重寫run()方法定義了一個新的線程類MyThread,其中run()方法的方法體表明瞭線程須要完成的任務,稱之爲線程執行體。當建立此線程類對象時一個新的線程得以建立,並進入到線程新建狀態。經過調用線程對象引用的start()方法,使得該線程進入到就緒狀態,此時此線程並不必定會立刻得以執行,這取決於CPU調度時機。
class MyRunnable implements Runnable { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } }
public class ThreadTest { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { Runnable myRunnable = new MyRunnable(); // 建立一個Runnable實現類的對象 Thread thread1 = new Thread(myRunnable); // 將myRunnable做爲Thread target建立新的線程 Thread thread2 = new Thread(myRunnable); thread1.start(); // 調用start()方法使得線程進入就緒狀態 thread2.start(); } } } }
讓一個線程等待另外一個線程完成才繼續執行。如A線程線程執行體中調用B線程的join()方法,則A線程被阻塞,知道B線程執行完爲止,A才能得以繼續執行。
讓當前的正在執行的線程暫停指定的時間,並進入阻塞狀態。在其睡眠的時間段內,該線程因爲不是處於就緒狀態,所以不會獲得執行的機會。即便此時系統中沒有任何其餘可執行的線程,出於sleep()中的線程也不會執行。所以sleep()方法經常使用來暫停線程執行。
當調用了新建的線程的start()方法後,線程進入到就緒狀態,可能會在接下來的某個時間獲取CPU時間片得以執行,若是但願這個新線程必然性的當即執行,直接調用原來線程的sleep(1)便可。
後臺線程主要是爲其餘線程(相對能夠稱之爲前臺線程)提供服務,或「守護線程」。如JVM中的垃圾回收線程。
生命週期:後臺線程的生命週期與前臺線程生命週期有必定關聯。主要體如今:當全部的前臺線程都進入死亡狀態時,後臺線程會自動死亡
每一個線程在執行時都具備必定的優先級,優先級高的線程具備較多的執行機會。每一個線程默認的優先級都與建立它的線程的優先級相同。main線程默認具備普通優先級。
設置線程優先級:setPriority(int priorityLevel)。參數priorityLevel範圍在1-10之間
當某個線程調用yiled()方法從運行狀態轉換到就緒狀態後,CPU從就緒狀態線程隊列中只會選擇與該線程優先級相同或優先級更高的線程去執行。
是指多線程環境下對共享資源的訪問可能會引發此共享資源的不一致性。所以,爲避免線程安全問題,應該避免多線程環境下對此共享資源的併發訪問。
對共享資源進行訪問的方法定義中加上synchronized關鍵字修飾,使得此方法稱爲同步方法。能夠簡單理解成對此方法進行了加鎖,其鎖對象爲當前方法所在的對象自身。多線程環境下,當執行此方法時,首先都要得到此同步鎖(且同時最多隻有一個線程可以得到),只有當線程執行完此同步方法後,纔會釋放鎖對象,其餘的線程纔有可能獲取此同步鎖,以此類推...
public synchronized void run() { }
使用同步方法時,使得整個方法體都成爲了同步執行狀態,會使得可能出現同步範圍過大的狀況,因而,針對須要同步的代碼能夠直接另外一種同步方式——同步代碼塊來解決。
synchronized (obj) { }
這三個方法主要都是用於多線程中,都是Object類中的本地方法。
在實際的多線程編程中,只有同步鎖對象調這三個方法,才能完成對多線程間的線程通訊。
wait():致使當前線程等待並使其進入到等待阻塞狀態。直到其餘線程調用該同步鎖對象的notify()或notifyAll()方法來喚醒此線程。
notify():喚醒在此同步鎖對象上等待的單個線程,若是有多個線程都在此同步鎖對象上等待,則會任意選擇其中某個線程進行喚醒操做,只有當前線程放棄對同步鎖對象的鎖定,纔可能執行被喚醒的線程。
notifyAll():喚醒在此同步鎖對象上等待的全部線程,只有當前線程放棄對同步鎖對象的鎖定,纔可能執行被喚醒的線程。
須要注意的是:
wait()方法執行後,當前線程當即進入到等待阻塞狀態,其後面的代碼不會執行;
notify()/notifyAll()方法執行後,將喚醒此同步鎖對象上的(任意一個-notify()/全部-notifyAll())線程對象,可是,此時還並無釋放同步鎖對象,也就是說,若是notify()/notifyAll()後面還有代碼,還會繼續進行,知道當前線程執行完畢纔會釋放同步鎖對象;
notify()/notifyAll()執行後,若是右面有sleep()方法,則會使當前線程進入到阻塞狀態,可是同步對象鎖沒有釋放,依然本身保留,那麼必定時候後仍是會繼續執行此線程,接下來同2;
wait()/notify()/nitifyAll()完成線程間的通訊或協做都是基於不一樣對象鎖的,所以,若是是不一樣的同步對象鎖將失去意義,同時,同步對象鎖最好是與共享資源對象保持一一對應關係;
當wait線程喚醒後並執行時,是接着上次執行到的wait()方法代碼後面繼續往下執行的。
做用就是獲得當前線程的對象。
經過currentThread()咱們能夠輕易的就獲得當前線程的名稱,咱們還能夠經過線程對象,獲得其餘的屬性。
注意:
currentThread()方法返回的是對當前正在執行的線程對象的引用,this表明的是當前調用它所在函數所屬的對象的引用
MySQL經常使用存儲引擎:InnoDB適用於頻繁維護修改插入等數據表,MyISAM適合少改寫,少插入的頻繁讀取的表。經常使用InnoDB存儲引擎
Innodb才支持事務
主要是爲了解決併發狀況下保持數據一致性的問題。
如下4個基本特徵:
Atomic(原子性):事務中包含的操做被看作一個邏輯單元,這個邏輯單元中的操做要麼所有成功,要麼所有失敗。
Consistency(一致性):只有合法的數據能夠被寫入數據庫,不然事務應該將其回滾到最初狀態。
Isolation(隔離性):事務容許多個用戶對同一個數據進行併發訪問,而不破壞數據的正確性和完整性。同時,並行事務的修改必須與其餘並行事務的修改相互獨立。
Durability(持久性):事務結束後,事務處理的結果必須可以獲得固化。
Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務
處理事務:spring的事務是經過「聲明式事務」的方式對事務進行管理,即在配置文件中進行聲明,經過AOP將事務切面切入程序,最大的好處是大大減小了代碼量,提升了工做效率。
百度一下
MVC是model-view-controler的簡稱。也就是模型-視圖-控制器。mvc是一種設計模式,他強制性的把應用程序的輸入、處理和輸出分開。mvc中的模型、視圖、控制器分別擔任着不一樣的任務。
視圖:視圖是用戶看到並與之交互的界面。視圖向用戶顯示相關的數據,並接受用戶的輸入。視圖不進行任何業務邏輯處理。
模型:模型表示業務數據和業務處理。至關於javaBean。一個模型能爲多個視圖提供數據。這提升了應用程序的重用性。
控制器:當用戶單擊web頁面中的提交按鈕時,控制器接收請求並調用相應的模型去處理請求。而後根據處理的結果調用相應的視圖來顯示處理的結構。
MVC的處理過程:首先控制器接收用戶的請求,調用相應的模型來進行業務處理,並返回數據給控制器。控制器調用相應的視圖來顯示處理的結構。並經過視圖呈現給用戶。如在項目中要對應MVC的話;View對應項目中的jsp,controler對應action,model對應service+dao層的業務邏輯和持久層的操做。
工做原理:
優化:
Hibernate對數據的緩存包括兩個級:一級緩存,在Session的級別上進行,主要是對象緩存,以其id爲鍵保存對象,在Session的生命期間存在;二級緩存,在SessionFactory的級別上進行,有對象緩存和查詢緩存,查詢緩存以查詢條件爲鍵保存查詢結果,在SessionFactory的生命期間存在,默認地,Hibernate只啓用一級緩存
優勢:
Hibernate是JDBC的輕量級的對象封裝,它是一個獨立的對象持久層框架。Hibernate能夠用在任何JDBC可使用的場合,例如Java應用程序的數據庫訪問代碼,DAO接口的實現類,甚至能夠是BMP裏面的訪問數據庫的代碼。
Hibernate是一個和JDBC密切關聯的框架,因此Hibernate的兼容性和JDBC驅動,和數據庫都有必定的關係,可是和使用它的Java程序,和App Server沒有任何關係,也不存在兼容性問題。
Hibernate不能用來直接和Entity Bean作對比,只有放在整個J2EE項目的框架中才能比較。而且即便是放在軟件總體框架中來看,Hibernate也是作爲JDBC的替代者出現的,而不是Entity Bean的替代者出現的。
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了很是輕量級的對象封裝,使得Java程序員能夠爲所欲爲的使用對象編程思惟來操控數據庫。
Hibernate能夠應用在任何使用JDBC的場合。
Hibernate 使用Java 反射機制而不是字節碼加強程序來實現透明性。
Hibernate 的性能很是好,由於它是個輕量級框架。映射的靈活性很出色。它支持各類關係數據庫,從一對一到多對多的各類複雜關係。
易於上手和掌握。
sql寫在xml裏,便於統一管理和優化。
解除sql與程序代碼的耦合。
提供映射標籤,支持對象與數據庫的orm字段關係映射
提供對象關係映射標籤,支持對象關係組建維護
提供xml標籤,支持編寫動態sql。
Mybatis優點MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。
MyBatis容易掌握,而Hibernate門檻較高。
Hibernate優點Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射。
Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。
Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。
Hibernate有更好的二級緩存機制,可使用第三方緩存。MyBatis自己提供的緩存機制不佳。
它基於IoC(Inversion of Control,反向控制)和AOP的構架多層j2ee系統的框架,但它不強迫你必須在每一層中必須使用Spring,由於它模塊化的很好,容許你根據本身的須要選擇使用它的某一個模塊;它實現了很優雅的MVC,對不一樣的數據訪問技術提供了統一的接口,採用IoC使得能夠很容易的實現bean的裝配,提供了簡潔的AOP並據此實現Transcation Managment,等等
事務控制:
低侵入式設計,代碼污染極低
獨立於各類應用服務器,基於Spring框架的應用,能夠真正實現Write Once,Run Anywhere的承諾
Spring的DI機制下降了業務對象替換的複雜性,提升了組件之間的解耦
Spring的AOP支持容許將一些通用任務如安全、事務、日誌等進行集中式管理,從而提供了更好的複用
Spring的ORM和DAO提供了與第三方持久層框架的良好整合,並簡化了底層的數據庫訪問
Spring並不強制應用徹底依賴於Spring,開發者可自由選用Spring框架的部分或所有
工做原理:
實現了MVC模式,層次結構清晰,使程序員只需關注業務邏輯的實現。
豐富的標籤庫,大大提升了開發的效率。
Struts2提供豐富的攔截器實現。
經過配置文件,就能夠掌握整個系統各個部分之間的關係。
異常處理機制,只需在配置文件中配置異常的映射,便可對異常作相應的處理。
Struts2的可擴展性高。
面向切面編程的思想在Strut2中也有了很好的體現。最重要的體現就是攔截器的使用
第一步:發起請求到前端控制器(DispatcherServlet)
第二步:前端控制器請求HandlerMapping查找 Handler,能夠根據xml配置、註解進行查找
第三步:處理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器調用處理器適配器去執行Handler
第五步:處理器適配器去執行Handler
第六步:Handler執行完成給適配器返回ModelAndView
第七步:處理器適配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一個底層對象,包括Model和view
第八步:前端控制器請求視圖解析器去進行視圖解析,根據邏輯視圖名解析成真正的視圖(jsp)
第九步:視圖解析器向前端控制器返回View
第十步:前端控制器進行視圖渲染,視圖渲染將模型數據(在ModelAndView對象中)填充到request域
第十一步:前端控制器向用戶響應結果工做流程:
優勢: