有一段話,我很喜歡:人會長大三次。第一次是在發現自己不是世界中心的時候。第二次是在發現即使再怎麼努力,終究還是有些事令人無能爲力的時候。第三次是在,明知道有些事可能會無能爲力,但還是會盡力爭取的時候。
作爲烏龜,我們可以去自己想去的地方。但是不要停止奔跑。
1.冒泡排序
針對 數組的 排序 ,其思想就是 逐個對比數大小 ,把大的數字放後面。
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
2.二分查找
針對數組 對半查找key 所在的位置
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
3.集合數組
public class MyStack {
private LinkedList link;
public MyStack() {
link = new LinkedList();
}
public void add(Object obj) {
link.addFirst(obj);
}
public Object get() {
return link.removeFirst();
}
public boolean isEmpty() {
return link.isEmpty();
}
}
/*
* MyStack的測試
*/
public class MyStackDemo {
public static void main(String[] args) {
// 創建集合對象
MyStack ms = new MyStack();
// 添加元素
ms.add("hello");
ms.add("world");
ms.add("java");
while(!ms.isEmpty()){
System.out.println(ms.get());
}
}
}
使用LinkedList模擬一個堆棧或者隊列數據模式 堆棧:先進後出 隊列:先進先出
4.Vector使用
Vector vector = new Vector<>();
vector.addElement("ss");
vector.addElement("8888");
vector.addElement("1231312432");
for (int i = 0; i < vector.size(); i++) {
String string = (String) vector.elementAt(i);
System.out.println("vector:" + string);
}
Enumeration enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
String object = (String) enumeration.nextElement();
System.out.println("vector:" + object);
}
5.TreeSet類
- 使用元素的自然順序對元素進行排序
或者根據創建 set 時提供的 Comparator 進行排序
所以排序有兩種方式
自然排序
比較器排序
具體取決於使用的構造方法。
public class TreeSetDemo {
public static void main(String[] args) {
// 創建集合對象
// 自然順序進行排序
TreeSet<Integer> ts = new TreeSet<Integer>();
// 創建元素並添加
// 20,18,23,22,17,24,19,18,24
ts.add(20);
ts.add(18);
ts.add(23);
ts.add(22);
ts.add(17);
ts.add(24);
ts.add(19);
ts.add(18);
ts.add(24);
// 遍歷
for (Integer i : ts) {
System.out.println(i);
}
}
}
6. 二叉樹
那麼二叉樹是怎麼把元素存進去,又是怎麼取出來的呢?
如果你弄懂了這個問題,那麼你就明白了二叉樹了
我們先來了解元素是如何存儲進去的?
第一個元素存儲的時候,直接作爲根節點存儲。
從第二個元素開始,每個元素從根節點開始比較
比根節點元素大,就放在右邊
比根節點元素小,就放在左邊
相等的話就忽略。
我們以上面的存儲的元素20,18,23,22,17,24,19,18,24來畫一個圖幫助大家理解
7.HashMap和Hashtable的區別?
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("android", "hello");
hm.put(null, "world");
hm.put("java", null);
System.out.println(hm);
Hashtable<String, String> ht = new Hashtable<String, String>();
ht.put("android", "hello");
ht.put(null, "world"); //NullPointerException
ht.put("java", null); // NullPointerException
System.out.println(ht);
在輸出結果中:HashMap會打印出{null=world, Java=null, Android=hello} 而在Hashtable中會報錯
所以我們就能得出他們的區別
HashMap:線程不安全,效率高。允許null鍵和null值
Hashtable:線程安全,效率低。不允許null鍵和null值
8.Collections類
- Collections類概述
針對集合進行操作的工具類,都是靜態方法。 - Collection和Collections的區別
Collection:是單列集合的頂層接口,有子接口List和Set。
Collections:是針對集合操作的工具類,有對集合進行排序和二分查找的方法 - Collections成員方法
public static < T> void sort(List list):排序 默認情況下是自然順序。
public static < T> int binarySearch(List< ?> list,T key):二分查找
public static < T> T max(Collection< ?> coll):最大值
public static void reverse(List< ?> list):反轉
public static void shuffle(List< ?> list):隨機置換
9.final,finally和finalize的區別?
final
最終的意思,可以修飾類,成員變量,成員方法
修飾類,類不能被繼承
修飾變量,變量是常量
修飾方法,方法不能被重寫
finally
是異常處理的一部分,用於釋放資源。
一般來說,代碼肯定會執行,特殊情況:在執行到finally之前jvm退出了
finalize
是Object類的一個方法,用於垃圾回收
這個題的難點就在於finalize,我們很少了解
子類重寫父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。
如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
如果被重寫的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
10.裝飾設計模式
字節流一次讀寫一個數組的速度明顯比一次讀寫一個字節的速度快很多,這是加入了數組這樣的緩衝區效果,Java本身在設計的時候,也考慮到了這樣的設計思想(裝飾設計模式),所以提供了字節緩衝區流
11.IO流
注意:我們除了用windows記事本能讀懂的數據用字符流以外,其餘的全部使用字節流。
// 第五種字符緩衝流一次讀寫一個字符串
private static void method5(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
// 第四種字節緩衝流一次讀寫一個字節數組
private static void method4(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
close()和flush()的區別?
close()關閉流對象,但是先刷新一次緩衝區。關閉之後,流對象不可以繼續再使用了。
flush()僅僅刷新緩衝區,刷新之後,流對象還可以繼續使用。
12.線程
由於線程是依賴進程而存在的,所以我們應該先創建一個進程出來。而進程是由系統創建的,所以我們應該去調用系統功能創建一個進程。Java是不能直接調用系統功能的,所以,我們沒有辦法直接實現多線程程序。但是呢?Java可以去調用C/C++寫好的程序來實現多線程程序。由C/C++去調用系統功能創建進程,然後由Java去調用這樣的東西,然後提供一些類供我們使用。我們就可以實現多線程程序了。
同步的特點:
多個線程
多個線程使用的是同一個鎖對象
好處:同步的出現解決了多線程的安全問題
弊端: 當線程相當多時,因爲每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程序的運行效率。
同步代碼塊的鎖對象可以時任意對象。
但是,當把同步關鍵字加在方法上,它的對象是this
當此方法爲精態方法時,它的對象是類的字節碼文件對象,也就是 類名.class
13.多線程生產者和消費者問題
什麼是生產者和消費者
簡單來說就是生產一個,消費一個,具體點就是
生產者 :先看是否有數據,有就等待;沒有就生產,生產完成之後通知消費者來消費數據
消費者:先看是否有數據,有就消費;沒有就等待,通知生產者生產數據
爲了處理這樣的問題,Java提供了一種機制,等待喚醒機制
抽象到現實:
比如 你到沙縣 吃個鴨腿飯! 如果老闆 剛好有一份弄好的鴨腿飯,那直接拿給你消費。沒有的話, 老闆自己立馬打個飯加點青菜蘿蔔 烤個鴨腿放上去,自己生產一份 拿去給你消費。
而你呢?如果有一份做好的,那麼就直接開搞吃,沒有的話就通知老闆 下單搞一份,在那默默等待咯。如果吃不夠,再叫老闆生產一份!
14.設計模式
面向對象思想設計原則
單一職責原則
其實就是開發人員經常說的”高內聚,低耦合”
開閉原則
核心思想是:一個對象對擴展開放,對修改關閉。其實開閉原則的意思就是:對類的改動是通過增加代碼進行的,而不是修改現有代碼。
里氏替換原則
核心思想:在任何父類出現的地方都可以用它的子類來替代。其實就是說:同一個繼承體系中的對象應該有共同的行爲特徵。
依賴注入原則
核心思想:要依賴於抽象,不要依賴於具體實現。
接口分離原則
核心思想:不應該強迫程序依賴它們不需要使用的方法。
迪米特原則
核心思想:一個對象應當對其他對象儘可能少的瞭解
設計模式概述
設計模式(Designpattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。
設計模式不是一種方法和技術,而是一種思想
設計模式和具體的語言無關,學習設計模式就是要建立面向對象的思想,儘可能的面向接口編程,低耦合,高內聚,使設計的程序可複用
學習設計模式能夠促進對面向對象思想的理解,反之亦然。它們相輔相成
設計模式的分類
創建型模式:簡單工廠模式,工廠方法模式,抽象工廠模式,建造者模式,原型模式,單例模式。(6個)
結構型模式:外觀模式、適配器模式、代理模式、裝飾模式、橋接模式、組合模式、享元模式。(7個)
行爲型模式:模版方法模式、觀察者模式、狀態模式、職責鏈模式、命令模式、訪問者模式、策略模式、備忘錄模式、迭代器模式、解釋器模式。(10個)
1.工廠方法模式
工廠方法模式中抽象工廠類負責定義創建對象的接口,具體對象的創建工作由繼承抽象工廠的具體類實現。
2.單例設計模式
單例模式就是要確保類在內存中只有一個對象,該實例必須自動創建,並且對外提供。
餓漢式:類一加載就創建對象
懶漢式:用對象的時候,纔去創建對象
面試主要面兩個思想,分別是:
懶加載思想(延遲加載)
線程安全問題(就要考慮下面3個方面)
是否多線程環境
b:是否有共享數據
c:是否有多條語句操作共享數據
如果都是,就會存在線程的安全問題,我們上面的懶漢式代碼是不完整的,應該給對象中的方法加上synchronized關鍵字,這樣纔算完整
public synchronized static Teacher getTeacher() {
if (t == null) {
t = new Teacher();
}
return t;
}
模版設計模式
模版方法模式就是定義一個算法的骨架,而將具體的算法延遲到子類中來實現
裝飾設計模式
裝飾模式就是使用被裝飾類的一個子類的實例,在客戶端將這個子類的實例交給裝飾類。是繼承的替代方案
在IO流中的裝飾模式應用
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(System.out)));