Java基礎(chǔ)+集合+多線程+JVM(一)

目錄
? ? 1 Java基礎(chǔ)
? ? 2 Java集合

? ? 3 Java多線程
? ? 4 JVM
? ? 5 常見問題匯總

參考資料
? ? ·《Java編程思想》
? ? ·《Java Web 技術(shù)內(nèi)幕》
? ? ·《Java 并發(fā)編程實(shí)戰(zhàn)》

1 Java基礎(chǔ)

1.1 對象

1.1.1 創(chuàng)建對象

1.1.1.1 引用

????用引用(reference)操縱對象。猶如遙控器和電視機(jī)的關(guān)系。

1.1.1.2 new關(guān)鍵字

????創(chuàng)建對象,并存儲(chǔ)在堆heap中。

1.1.1.3 特例:基本類型

(1)基本類型與包裝類

? ? ? ? · 裝箱過程是通過調(diào)用valueOf方法(Integer Integer.valueOf(int))實(shí)現(xiàn)的,拆箱為xxxValue()(int Integer.intValue())。

? ? ? ? · Integer裝箱時(shí),在[-128, 127]之間不創(chuàng)建新對象,否則創(chuàng)建新對象。

? ? ? ? · Integer、Short、Byte、Character、Long類似。Double、Float裝箱類似,每次創(chuàng)建新對象。

? ? ? ? ·?當(dāng) "=="運(yùn)算符的兩個(gè)操作數(shù)都是 包裝器類型的引用,則是比較指向的是否是同一個(gè)對象,而如果其中有一個(gè)操作數(shù)是表達(dá)式(即包含算術(shù)運(yùn)算)則比較的是數(shù)值(即會(huì)觸發(fā)自動(dòng)拆箱的過程)。另外,對于包裝器類型,equals方法并不會(huì)進(jìn)行類型轉(zhuǎn)換。

demo:

public class Main {

????public static void main(String[] args) {

????????Integer a = 1;

????????Integer b = 2;

????????Integer c = 3;

????????Integer d = 3;

????????Integer e = 321;

????????Integer f = 321;

????????Long g = 3L;

????????Long h = 2L;

????????System.out.println(c==d);

????????System.out.println(e==f);

????????System.out.println(c==(a+b));

????????System.out.println(c.equals(a+b));

????????System.out.println(g==(a+b));

????????System.out.println(g.equals(a+b));

????????System.out.println(g.equals(a+h));

????}

}

true? ?false? ? true? ? true? ?true? ? false? ? ?true

  第一個(gè)和第二個(gè)輸出結(jié)果沒有什么疑問。第三句由于? a+b包含了算術(shù)運(yùn)算,因此會(huì)觸發(fā)自動(dòng)拆箱過程(會(huì)調(diào)用intValue方法),因此它們比較的是數(shù)值是否相等。而對于c.equals(a+b)會(huì)先觸發(fā)自動(dòng)拆箱過程,再觸發(fā)自動(dòng)裝箱過程,也就是說a+b,會(huì)先各自調(diào)用intValue方法,得到了加法運(yùn)算后的數(shù)值之后,便調(diào)用Integer.valueOf方法,再進(jìn)行equals比較。同理對于后面的也是這樣,不過要注意倒數(shù)第二個(gè)和最后一個(gè)輸出的結(jié)果(如果數(shù)值是int類型的,裝箱過程調(diào)用的是Integer.valueOf;如果是long類型的,裝箱調(diào)用的Long.valueOf方法)。

(2)存儲(chǔ)位置:堆棧

(3)8中基本類型的字節(jié)大小。

圖1-1 基本類型字節(jié)大小

1.1.2 不需要手動(dòng)銷毀對象

? ? · 作用域:花括號(hào)決定

? ? · GC機(jī)制決定不需要手動(dòng)銷毀對象。

1.1.3 類

(1)成員變量(字段)、成員函數(shù)(方法)。其中對于基本類型的成員變量有默認(rèn)值。

(2)Java程序:

? ? ? ? · 無“向前引用”問題

? ? ? ? · 通配符 *,import java.lang.*

? ? ? ? · static 修飾時(shí),屬于類屬性,與實(shí)例無關(guān)。

? ? ? ? · java.lang 在程序中被自動(dòng)導(dǎo)入。

? ? ? ? · 編碼風(fēng)格:命名規(guī)則采用“駝峰命名法”。類名的首字母要大寫;如果類名由幾個(gè)單詞構(gòu)成,則并在一起,每個(gè)內(nèi)部單詞的首字母采用大寫;方法、字段以及對象引用名稱等與類相似,只是這些標(biāo)識(shí)符的第一個(gè)字母采用小寫。

1.1.4 對象的構(gòu)成

Java的對象頭和對象組成詳解_Clarence-CSDN博客

1.2 操作符

1.2.1 關(guān)系操作符

? ? “==”與equals()區(qū)別:

? ? · ==對基本類型來說比較數(shù)值,對引用類型來說比較的是內(nèi)存地址。

? ? · equals()在沒有被覆蓋時(shí),等價(jià)于“==”。當(dāng)被覆蓋時(shí),一般比較的是對象的內(nèi)容。

? ? · String對象中的equals()方法被覆蓋過了,比較的是內(nèi)容。

1.2.2 按位操作符

? ? 非(~)不能用于布爾類型,可用!(邏輯操作符)。

1.2.3 移位符

? ? · >>> “無符號(hào)”右移

? ? · char、byte、short 移位前需要轉(zhuǎn)int類型

1.2.4 字符串操作

? ? String中的“+”操作符底層原理:

? ? ? ? new StringBuffer(str).append(c).toString();

1.2.5 類型轉(zhuǎn)換(cast)

· 基本數(shù)據(jù)類型

? ? · 窄化轉(zhuǎn)換(危險(xiǎn))

? ? · 擴(kuò)展轉(zhuǎn)換(安全)

1.3 控制執(zhí)行

????foreach 用于數(shù)組和容器

? ? ? ? ? ? · 任何一個(gè)返回?cái)?shù)組的方法 for(String str : getString()){ }

? ? ? ? ? ? · 任何Iterable對象

1.4 初始化與清理

1.4.1 構(gòu)造器

? ? 如果已經(jīng)定義了一個(gè)構(gòu)造器(有/無參),編譯器不會(huì)自動(dòng)創(chuàng)建默認(rèn)構(gòu)造器,此時(shí)調(diào)用默認(rèn)無參構(gòu)造器報(bào)錯(cuò)

1.4.2 方法重載

? ? 同一個(gè)類中,方法名相同,參數(shù)的類型、個(gè)數(shù)、順序不同。

1.4.3 this

? ? · 獲得當(dāng)前對象的引用

? ? · 只能在方法內(nèi)部使用

? ? · 構(gòu)造器之間調(diào)用時(shí),this 只能最多有一個(gè),且只能放第一行

? ? · 不能再staitc修飾的方法中調(diào)用

1.4.4 終結(jié)處理與垃圾回收

1.4.4.1 finalize()方法

(1)finalize()方法是Object類中提供的一個(gè)方法,在GC準(zhǔn)備釋放對象所占用的內(nèi)存空間之前,它將首先調(diào)用finalize()方法。其在Object中定義如下:protected void finalize() throws Throwable { }

(2)finalize()調(diào)用的時(shí)機(jī)

????????與C++的析構(gòu)函數(shù)(對象在清除之前析構(gòu)函數(shù)會(huì)被調(diào)用)不同,在Java中,由于GC的自動(dòng)回收機(jī)制,因而并不能保證finalize方法會(huì)被及時(shí)地執(zhí)行(垃圾對象的回收時(shí)機(jī)具有不確定性),也不能保證它們會(huì)被執(zhí)行(程序由始至終都未觸發(fā)垃圾回收)。

public class Finalizer {

????@Override

????protected void finalize() throws Throwable {

????????System.out.println("Finalizer-->finalize()");

????}

????public static void main(String[] args) {

????????Finalizer f = new Finalizer();

????????f = null;

????}

}

//無輸出

public class Finalizer {

????@Override

????protected void finalize() throws Throwable {

????????System.out.println("Finalizer-->finalize()");

????}

????public static void main(String[] args) {

????????Finalizer f = new Finalizer();

????????f = null;

????????System.gc();//手動(dòng)請求gc

????}

}

//輸出 Finalizer-->finalize()

(3)?什么時(shí)候應(yīng)該使用它

????finalize()方法中一般用于釋放非Java 資源(如打開的文件資源、數(shù)據(jù)庫連接等),或是調(diào)用非Java方法(native方法)時(shí)分配的內(nèi)存(比如C語言的malloc()系列函數(shù))。

(4)為什么避免使用

????首先,由于finalize()方法的調(diào)用時(shí)機(jī)具有不確定性,從一個(gè)對象變得不可到達(dá)開始,到finalize()方法被執(zhí)行,所花費(fèi)的時(shí)間這段時(shí)間是任意長的。我們并不能依賴finalize()方法能及時(shí)的回收占用的資源,可能出現(xiàn)的情況是在我們耗盡資源之前,gc卻仍未觸發(fā),因而通常的做法是提供顯示的close()方法供客戶端手動(dòng)調(diào)用。

????另外,重寫finalize()方法意味著延長了回收對象時(shí)需要進(jìn)行更多的操作,從而延長了對象回收的時(shí)間。

1.4.4.2 顯示GC( system.gc() )也不一定執(zhí)行

1.4.4.3 GC算法

(1) 引用計(jì)數(shù)

? ? ? ? ? ? 描述工作方式,未實(shí)現(xiàn)。

(2)復(fù)制

(3)標(biāo)記清除

(4)標(biāo)記整理

(5)分代收集機(jī)制

? ? ? ? · 新生代(使用復(fù)制算法)

? ? ? ? · 老年代(使用標(biāo)記清除和標(biāo)記整理算法)

1.4.5 初始化順序

(1)字段在任何方法(包括構(gòu)造器)之前得到初始化。

(2)static

? ? ? ? · 只有在必要時(shí)刻才會(huì)進(jìn)行(訪問該類,因?yàn)閟taic修飾屬于類屬性)

? ? ? ? · 代碼塊加載順序

? ? ? ? ? ? 靜態(tài)代碼塊(類加載的時(shí)候加載一次)---> 普通代碼塊(在實(shí)例化時(shí)加載,可加載多次)---> 構(gòu)造函數(shù)(先調(diào)用父類構(gòu)造函數(shù))

1.5 訪問控制

(1)每個(gè).java文件只能包含一個(gè)public類

(2)訪問權(quán)限修飾詞

? ? ? ? ? ? · 包訪問權(quán)限(默認(rèn))

? ? ? ? ? ? · public 對每個(gè)人可見

? ? ? ? ? ? · private 僅該類可見(子類可以通過set、get方法調(diào)用private屬性),不可修飾類

? ? ? ? ? ? · protected 繼承的子類可見? 不可修飾類

? ? ? ? ? ? · 將構(gòu)造函數(shù)用private修飾,可以做成單例模式。

// 利用private修飾構(gòu)造器,完成單例模式

Class Demo {

? ? private Demo(){};

? ? private static Demo p = new Demo();

? ? public static Demo access(){

? ? ? ? return p;

????}

}

1.6 復(fù)用類

1.6.1 組合類

? ? 在類的字段中包含對其他類的引用。

1.6.2 繼承

? ? 所有類都隱式繼承Object類。

? ? Object類的方法:

圖1-2 Object類

? ? · 關(guān)于clone方法:Java 淺拷貝和深拷貝 - 簡書、java中clone方法的理解(深拷貝、淺拷貝)_xinghuo0007的博客-CSDN博客

(1)語法

? ? ? ? · 父類中,成員變量用private,成員方法用public

? ? ? ? · 使用extends關(guān)鍵字

? ? ? ? · 使用super.function()在覆蓋的方法中訪問父類方法。

(2)初始化

? ? ? ? · 子類沒有構(gòu)造器,調(diào)用父類的

? ? ? ? · 基類先加載。基類在導(dǎo)出類構(gòu)造器可以訪問它之前,就已經(jīng)完成初始化。

(3)覆蓋(復(fù)寫)

? ? ? ? · 重載基類的方法,基類本身的方法并不會(huì)被屏蔽。

? ? ? ? · 只想覆蓋 @override注解(不加注解,基類的方法依然存在)

(4)向上轉(zhuǎn)型

1.6.3 final

(1)數(shù)據(jù)

? ? ? ? · 編譯時(shí)常量,無法創(chuàng)建setter方法

? ? ? ? · 運(yùn)行時(shí)初始化并不變

? ? ? ? · 使用前總被初始化

(2)方法

? ? ? ? 防止繼承類修改。(private 隱式在子類中指定為final)

(3)類

? ? ? ? 不可被繼承,所有方法隱式為final

1.6.4 初始化及加載

(1)有基類,先加載

(2)加載static

(3)new 先加載基類構(gòu)造器,再加載子類構(gòu)造器。

1.7 多態(tài)

? ? 面向?qū)ο蟮娜筇卣鳎悍庋b、繼承、多態(tài)。

1.7.1 方法調(diào)用綁定

(1)前期綁定:在程序編譯期間綁定

(2)后期綁定:在運(yùn)行時(shí)綁定(動(dòng)態(tài)綁定),static方法不具有多態(tài)。

1.7.2 多態(tài)設(shè)計(jì)

? ? · 繼承

? ? · 組合:通過類似set方法,修改成員變量

? ? · 接口

1.7.3 向上轉(zhuǎn)型(安全)

1.8 接口

? ? 提供了一種將接口和實(shí)現(xiàn)分離的方法。

1.8.1 抽象類

(1)包含抽象方法的類 abstract

? ? ? ? 可以含有構(gòu)造方法,子類實(shí)例化時(shí),先調(diào)用父類構(gòu)造器。

(2)繼承

? ? ? ? · 子類必須實(shí)現(xiàn)抽象方法

? ? ? ? · 可以繼續(xù)使用abstact修飾,可以不用實(shí)現(xiàn)抽象方法

(3)不需要所有方法都是抽象

(4)不可以實(shí)例化

1.8.2 接口interface

(1)所以方法都抽象,且隱式為public的

(2)可以包含域,隱式為static和final的

(3)實(shí)現(xiàn):子類實(shí)現(xiàn)所有接口方法 implements

(4)不可以實(shí)例化

1.8.3 多重繼承

(1)extends 一個(gè)基類 implements 多個(gè)接口

(2)接口之間可以使用extends繼承

(3)可以向上轉(zhuǎn)型為任意接口

1.8.4 設(shè)計(jì)模式

(1)策略設(shè)計(jì)模式:根據(jù)所傳參對象不同,具有不同方法(重載)

(2)適配器設(shè)計(jì)模式:接受擁有的接口,產(chǎn)生所需要的對象

(3)工廠方法設(shè)計(jì)模式:返回接口的某個(gè)實(shí)現(xiàn)的對象

1.9 異常處理

(1)基本異常Exception

? ? ? ? · new 異常對象

? ? ? ? · 異常參數(shù):

? ? ? ? ? ? ? ? · 默認(rèn)構(gòu)造器

? ? ? ? ? ? ? ? · 字符串

(2)捕獲異常

? ? ? ? · try

? ? ? ? · catch

? ? ? ? ? ? 異常處理的結(jié)果有終止模型和恢復(fù)模型兩種。Java支持終止模型,認(rèn)為錯(cuò)誤非常關(guān)鍵,以至于程序無法返回到異常發(fā)生的地方繼續(xù)執(zhí)行,一旦異常被拋出,就表明錯(cuò)誤已無法挽回,也不能回來繼續(xù)執(zhí)行。

? ? ? ? · finally

? ? ? ? ? ? ? ? · 作用:把內(nèi)存之外的資源恢復(fù)到初始狀態(tài),如已經(jīng)打開的文件或者網(wǎng)絡(luò)等。
? ? ? ? ? ? ? ? · 含有return時(shí),覆蓋其他return。

(3)自定義異常:extends Exception 異?;?/p>

(4)異常說明 throws

(5)發(fā)送異常時(shí)的清理:在創(chuàng)建需要清理的對象之后,立即進(jìn)入try-catch-fianlly(嵌套)

(6)java.lang.Throwable

圖1-3 異常類

? ? ? ? · Error(錯(cuò)誤):是程序無法處理的錯(cuò)誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。編譯時(shí)和系統(tǒng)錯(cuò)誤。

? ? ? ? · Exception(異常):是程序本身可以處理的異常。可以被拋出的異常。

1.10 字符串

1.10.1 String對象不可變

? ? 定義:private final byte/char value[] (byte定義是JDK1.9出現(xiàn)的)

字符串與常量池的關(guān)系:Java提高篇之常量池_#include-CSDN博客

1.10.2? “+”“+=”的重載

? ? ? ? · java中僅有的兩個(gè)重載過的操作符

? ? ? ? · “+”底層用了StringBuffer()的append()和toString()方法。

1.10.3 正則表達(dá)式

(1)創(chuàng)建正則 java.util.regex.Pattern

(2)表達(dá)式

? ? ? ? · \\\\ 普通的反斜線

? ? ? ? · \\d 一個(gè)數(shù)字

? ? ? ? · split( regex )

? ? ? ? · replaceAll(regx,String)

正則表達(dá)式參考:Java正則表達(dá)式

1.10.4 對比

(1)StringBuilder

? ? ? ? · extends AbstractStringBuilder,不用final修飾

? ? ? ? · 線程不安全

(2)StringBuffer

? ? ? ? · extends AbstractStringBuilder

? ? ? ? · 線程安全,對方法加同步鎖

(3)常用方法:append、insert、indexOf、toString()

1.11 類型信息

1.11.1 RTTI

? ? ? ? 運(yùn)行時(shí)類型識(shí)別。

? ? (1)“傳統(tǒng)”,假定在編譯時(shí)知道了所有類型

? ? (2)“反射”,在運(yùn)行時(shí)發(fā)現(xiàn)和使用類的信息

1.11.2 Class對象

? ? java.lang.Class類

(1)被編譯后產(chǎn)生,保存在.class文件中

(2)用來創(chuàng)建類的所有對象。創(chuàng)建前,用類加載器加載Class對象

(3)獲取Class對象的方式:

? ? ? ? · Class c1 = Class.forName(“類的全限定名”);

? ? ? ? · Class c2 = 類名.class;

? ? ? ? · Class c3 = this.getClass();

1.11.3 RTTI應(yīng)用場景

(1)類型轉(zhuǎn)換

(2)class對象

(3)instance of

(4)反射

? ? ????class類與java.lang.reflect類庫

(5)JDK動(dòng)態(tài)代理

? ? ? ? Proxy.newProxyInstance(類加載器,接口列表(目標(biāo)接口),InvocationHandler實(shí)例)

1.12 IO

1.12.1 分類

(1)基于字節(jié)操作:InputStream/OutputStream

? ? ? ? 數(shù)據(jù)持久化或者網(wǎng)絡(luò)傳輸都是以字節(jié)進(jìn)行的。

(2)基于字符操作:Reader/Writer

(3)基于磁盤操作:File

(4)基于網(wǎng)絡(luò)操作:Socket

? ? InputStreamReader從字節(jié)到字符轉(zhuǎn)化,需要制定字符集

????OutputStreamWriter從字符到字節(jié)轉(zhuǎn)化

字符和字節(jié)的區(qū)別:字節(jié)與字符的區(qū)別 | 菜鳥教程

1.12.2 模式

(1)BIO

? ? ? ? · 同步阻塞

? ? ? ? · 面向流

? ? ? ? · 數(shù)據(jù)讀取阻塞在線程中

(2)NIO

? ? ? ? · 同步非阻塞

? ? ? ? · 面向緩沖、基于通道,有選擇器

? ? ? ? · channel、selector、Buffer

(3)AIO

? ? ? ? · 異步非阻塞

? ? ? ? · 基于事件和回調(diào)機(jī)制

1.12.3 磁盤IO工作模式

(1)調(diào)用方式

? ? ? ? ?讀取和寫入文件IO操作都調(diào)用操作系統(tǒng)提供的接口,因?yàn)榇疟P設(shè)備是由操作系統(tǒng)管理的。

? ? 系統(tǒng)調(diào)用read()/write() ----》內(nèi)核空間(含緩存機(jī)制) -----》用戶空間

(2)訪問文件方式

? ? · 標(biāo)準(zhǔn)訪問文件方式:先查緩存,再查磁盤。write()時(shí),內(nèi)核緩存同步sync時(shí)間由操作系統(tǒng)決定。

圖1-4?標(biāo)準(zhǔn)訪問文件

? ? · 直接IO: 不經(jīng)過內(nèi)核空間

圖1-5 直接IO方式

? ? · 同步訪問文件:數(shù)據(jù)寫到磁盤才返回成功標(biāo)志給應(yīng)用程序。

圖1-6 同步訪問文件

? ? · 異步訪問文件:不阻塞等待

圖1-7 異步訪問文件

1.12.4 Java序列化技術(shù)

? ? (1)java序列化技術(shù)就是將一個(gè)對象轉(zhuǎn)化成一串二進(jìn)制表示的字節(jié)數(shù)組,通過保存或轉(zhuǎn)移這些字節(jié)數(shù)據(jù)來達(dá)到持久化的目的。

? ? (2)對象必須繼承java.io.Serializable接口。

? ? (3)反序列化時(shí),必須有原始類作為模板,才能將這個(gè)對象還原。

1.12.5 NIO

1.12.5.1 簡介

????Java NIO(New IO)是一個(gè)可以替代標(biāo)準(zhǔn)Java IO API的IO API(從Java 1.4開始),Java NIO提供了與標(biāo)準(zhǔn)IO不同的IO工作方式。

· Java NIO: Channels and Buffers(通道和緩沖區(qū))
????????標(biāo)準(zhǔn)的IO基于字節(jié)流和字符流進(jìn)行操作的,而NIO是基于通道(Channel)和緩沖區(qū)(Buffer)進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。

· Java NIO: Non-blocking IO(非阻塞IO)
????????Java NIO可以讓你非阻塞的使用IO,例如:當(dāng)線程從通道讀取數(shù)據(jù)到緩沖區(qū)時(shí),線程還是可以進(jìn)行其他事情。當(dāng)數(shù)據(jù)被寫入到緩沖區(qū)時(shí),線程可以繼續(xù)處理它。從緩沖區(qū)寫入通道也類似。

· Java NIO: Selectors(選擇器)
????????Java NIO引入了選擇器的概念,選擇器用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)的線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。

圖1-8 傳統(tǒng)IO
圖1-9 NIO

1.12.5.2?Buffers緩沖區(qū)

(1)java.nio包中定義對基本類型的容器。

  Buffer就像一個(gè)數(shù)組,可以保存多個(gè)相同類型的數(shù)據(jù)。根據(jù)類型不同(boolean除外),有以下Buffer常用子類:

? ? ·ByteBuffer

? ? ·CharBuffer

? ? ·ShortBuffer

? ? ·IntBuffer

? ? ·LongBuffer

? ? ·FloatBuffer

? ? ·DoubleBuffer

(2)屬性

? ? ? ? ·容量(capacity):表示Buffer最大數(shù)據(jù)容量,緩沖區(qū)容量不能為負(fù),并且建立后不能修改。

? ? ? ? ·限制(limit):第一個(gè)不應(yīng)該讀取或者寫入的數(shù)據(jù)的索引,即位于limit后的數(shù)據(jù)不可以讀寫。緩沖區(qū)的限制不能為負(fù),并且不能大于其容量(capacity)。

? ? ? ? ·位置(position):下一個(gè)要讀取或?qū)懭氲臄?shù)據(jù)的索引。緩沖區(qū)的位置不能為負(fù),并且不能大于其限制(limit)。

? ? ? ? ·標(biāo)記(mark)與重置(reset):標(biāo)記是一個(gè)索引,通過Buffer中的mark()方法指定Buffer中一個(gè)特定的position,之后可以通過調(diào)用reset()方法恢復(fù)到這個(gè)position。

(3)分類

? ? · 非直接緩沖區(qū):通過allocate() 方法分配緩沖區(qū),將緩沖區(qū)建立在 JVM 的內(nèi)存中。數(shù)據(jù)存儲(chǔ)傳輸需要先復(fù)制到內(nèi)存地址空間,再到磁盤。

圖1-10 非直接緩沖區(qū)

? ? · 直接緩沖區(qū)

? ? ? ? ·通過allocateDirect() 方法分配直接緩沖區(qū),將緩沖區(qū)建立在物理內(nèi)存中。可以提高效率。

? ? ? ? · 也可以通過FileChannel 的 map() 方法 將文件區(qū)域直接映射到內(nèi)存中來創(chuàng)建。

圖1-11 直接緩沖區(qū)

1.12.5.3 Channels通道

(1)作用

????????表示打開到IO 設(shè)備(例如:文件、套接字)的連接。若需要使用NIO 系統(tǒng),需要獲取用于連接 IO 設(shè)備的通道以及用于容納數(shù)據(jù)的緩沖區(qū)。然后操作緩沖區(qū),對數(shù)據(jù)進(jìn)行處理。Channel 負(fù)責(zé)傳輸, Buffer 負(fù)責(zé)存儲(chǔ)。

(2)java.nio.channels.Channel 接口:

? ? ? ? ·FileChannel

? ? ? ? ·SocketChannel

? ? ? ? ·ServerSocketChannel

? ? ? ? ·DatagramChannel

(3)分散讀取、聚集寫入

? ??????????scattering Reads:將通道中的數(shù)據(jù)分散到多個(gè)緩沖區(qū)中。

? ??????????gathering Writes:將多個(gè)緩沖區(qū)的數(shù)據(jù)聚集到通道中

圖1-12 分散讀取、聚集寫入

1.12.5.4 阻塞與非阻塞

(1)阻塞:客戶端連接請求時(shí),服務(wù)器只能等待連接請求,不能處理其他事情。

(2)非阻塞:客戶端連接注冊到多路復(fù)用器上,當(dāng)輪詢到連接有I/O請求時(shí),才啟動(dòng)線程處理。

(3)幾種IO模式的線程之間對比

????BIO:同步阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)連接一個(gè)線程,即客戶端有連接請求時(shí)服務(wù)器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理,如果這個(gè)連接不做任何事情會(huì)造成不必要的線程開銷,當(dāng)然可以通過線程池機(jī)制改善。?

????NIO:同步非阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)請求一個(gè)線程,即客戶端發(fā)送的連接請求都會(huì)注冊到多路復(fù)用器上,多路復(fù)用器輪詢到連接有I/O請求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。?

????AIO(NIO.2):異步非阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)有效請求一個(gè)線程,客戶端的I/O請求都是由OS先完成了再通知服務(wù)器應(yīng)用去啟動(dòng)線程進(jìn)行處理。?

? ? 偽異步:使用線程池管理

圖1-13 IO模型線程對比

1.12.5.5 Selector選擇器

(1)SelectionKey類

????在SelectionKey類的源碼中我們可以看到如下的4中屬性,四個(gè)變量用來表示四種不同類型的事件:可讀、可寫、可連接、可接受連接

? ? ? ? ·SelectionKey.OP_CONNECT

? ? ? ? ·SelectionKey.OP_ACCEPT

? ? ? ? ·SelectionKey.OP_READ

? ? ? ? ·SelectionKey.OP_WRITE

????如果你對不止一種事件感興趣,那么可以用“位或”操作符將常量連接起來,如下:

????????int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

圖1-14 選擇器

1.12.5.6 NIO的Socket請求

圖 1-15 NIO的Socket請求

? ? 分為兩個(gè)線程共工作,一個(gè)監(jiān)聽客戶端連接,一個(gè)用于處理數(shù)據(jù)交互。

1.13 JPA

(1)Java Persistence API 持久層API

? ??????JPA僅僅是一種規(guī)范,也就是說JPA僅僅定義了一些接口,而接口是需要實(shí)現(xiàn)才能工作的。所以底層需要某種實(shí)現(xiàn)

(2)基于O/R映射的標(biāo)準(zhǔn)規(guī)范

(3)主要實(shí)現(xiàn):Hibernate、EclipseLink、openJPA

(4)提供

? ? ? ? · XML或注解,將實(shí)體對象持久化到數(shù)據(jù)庫中。@Entity、@Table、@Column、@Transient

? ? ? ? · API,用來操作實(shí)體對象,執(zhí)行CRUD

? ? ? ? · JPQL查詢語句

(5)避免字段持久化到數(shù)據(jù)庫方法

? ? ? ? · static?java序列化之-static|transient 修飾的字段能否被序列化?_CD-CSDN博客

? ? ? ? · final

? ? ? ? · transient 也可以在Java中修飾,防止序列化。

? ? ? ? · @Transient

2 Java集合

2.1 泛型

? ? 指定容器可以保存的類型,在編譯器檢查錯(cuò)誤。

2.2 分類

? ? Java容器類類庫的用途是“保存對象”。

2.2.1 Collection

? ? · Collection容器繼承了Iterable接口( 實(shí)現(xiàn)iterator()方法 ),都可以使用foreach。

? ? · Collection容器都覆蓋了toString(),可以直接使用print()

2.2.1.1 List表

(1)必須按照插入的順序保存元素

(2)常見接口方法

? ? · boolean add(E e); 在尾部追加元素? ? ? ? · void add(int index, E element)?

?????· void clear()????????????????????????????????????????????· boolean contains(Object o)? ? ? ? ? ? ? ? ??

? ? ?· E get(int index);獲取指定下標(biāo)的元素? ? · int indexOf(Object o)獲取指定元素的下標(biāo)

? ? ?· boolean isEmpty() 判斷是否為空? ? ? ? ? · E remove(int index / Object o) 移除? ? ? ? ? ? ? ? ? ?

? ? ?· E set(int index, E element) 修改元素? ? · int size() 獲得大小? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ?· Object[] toArray[] 轉(zhuǎn)化為數(shù)組

2.2.1.2 Set

(1)不能用重復(fù)元素

(2)常見接口方法

? ? · boolean add(E e)? ? ? ? · void clear()? ? ?· boolean contains(Object o)

? ? · boolean isEmpty()? ? ? ?· boolean remove(Object o)? ? ? ?· int size()

? ? · Object[] toArray()

2.2.1.3 Queue

(1)按照排隊(duì)規(guī)則來確定對象產(chǎn)生的順序

(2)@常見接口方法

? ? · Throws exception

? ? ? ? · boolean add(E e)? ? ? · E remove()?返回并刪除頭元素? ? ? · E element() 返回頭元素

? ? · Returns special value

? ? ? ? · boolean offer(E e)? ? ? · E poll() 返回并彈出頭節(jié)點(diǎn)? ? ? ? ? ? · E peek() 返回頭元素

2.2.2 Map

(1)一組成對的“鍵值對”對象,允許使用鍵來查找值

(2)常見接口方法

? ? · void clear()? ? ? ? ? · boolean containsKey(Object key)? ? ?

? ? · boolean containsValue(Object value)? ?· Set<Map.Entry<K,V>> entrySet()? ? ? ??

????· boolean equals(Object o)? ? ? ? ? ? ? ? ? ? ?· Object get(Object key)

? ? · boolean isEmpty()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? · Object put(Object k, Object v)?會(huì)覆蓋前面的值? ? ? ?

????· Object remove(Object key)

????· default boolean replace(Object key, Object value, Object newValue)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

????· int size()? ? ? ? · remove(Object key)????

? ? ·?getOrDefault(Object key, V defaultValue)

? ? 說明:

? ? ? ? 調(diào)用Map.entrySet(),將集合中的映射關(guān)系對象存儲(chǔ)Set中。迭代Set集合,通過entry的getKey()和getValue()方法獲取映射關(guān)系對象。

2.3 迭代器Iterator

2.3.1 概念

? ? · 迭代器是一個(gè)對象,它的工作是遍歷并選擇序列中的對象,而客戶端程序員不必知道或關(guān)心該序列底層的結(jié)構(gòu)。

? ? · 迭代器只能單向移動(dòng)。

? ? · 不能對正在被迭代的集合進(jìn)行結(jié)構(gòu)上的改變,否則拋出異常。但可以使用iterator自己的remove方法

2.3.2 使用

(1)使用iterator()返回一個(gè)Iterator對象,并準(zhǔn)備返回序列的第一個(gè)元素。

(2)使用next()獲得序列的下一個(gè)元素

(3)使用hasNext()檢查序列中是否還有元素

(4)使用remove()將迭代器新近返回的元素刪除

public class Demo{

? ? public static void mian(String[] args){

? ? ? ? List<Pet> pets = Pets.arrayList(12);
? ? ? ? Iterator<Pet> it = pets.iteratror();
? ? ? ? while(it.hasNext()){
? ? ? ? ? ? Pet p = it.next();
? ??????????system.out.print(p);
????????}
? ? ? ? for(Pet p : pets){
? ? ? ? ? ? system.out.print(p);
????????}

? ? }

}

使用foreach語法更簡潔。

2.4 List的實(shí)現(xiàn)

2.4.1 ArrayList

2.4.1.1 基本特性

(1)擅長于隨機(jī)訪問元素,但插入和移除元素慢

(2)線程不安全,底層為Object數(shù)組

2.4.1.2 擴(kuò)容機(jī)制

(1)無參構(gòu)造時(shí),初始為空數(shù)組。當(dāng)添加第一個(gè)元素時(shí),擴(kuò)為10(默認(rèn))。

(2)填滿時(shí),自動(dòng)擴(kuò)容,變?yōu)樵瓉淼?.5倍左右(奇數(shù)偶數(shù)不同)。

2.4.2 LinkedList

(1)插入刪除代價(jià)較低,但隨即訪問慢。

(2)線程不安全,底層為雙向鏈表。

(3)沒有實(shí)現(xiàn)RandomAccess接口(標(biāo)識(shí)是否具有隨機(jī)訪問能力)。

(4)實(shí)現(xiàn)了基本的List接口,同時(shí)添加了可以使用其作棧、隊(duì)列或者雙端隊(duì)列的方法。

2.4.3 Vector

(1)Vector簡介

Vector 是矢量隊(duì)列,它是JDK1.0版本添加的類。繼承于AbstractList,實(shí)現(xiàn)了List, RandomAccess, Cloneable這些接口。

Vector 繼承了AbstractList,實(shí)現(xiàn)了List;所以,它是一個(gè)隊(duì)列,支持相關(guān)的添加、刪除、修改、遍歷等功能。

Vector 實(shí)現(xiàn)了RandmoAccess接口,即提供了隨機(jī)訪問功能。RandmoAccess是java中用來被List實(shí)現(xiàn),為List提供快速訪問功能的。在Vector中,我們即可以通過元素的序號(hào)快速獲取元素對象;這就是快速隨機(jī)訪問。

Vector 實(shí)現(xiàn)了Cloneable接口,即實(shí)現(xiàn)clone()函數(shù)。它能被克隆。

和ArrayList不同,Vector中的操作是線程安全的。

(2)底層分析

? ? ?·Vector實(shí)際上是通過一個(gè)數(shù)組去保存數(shù)據(jù)的。當(dāng)我們構(gòu)造Vecotr時(shí);若使用默認(rèn)構(gòu)造函數(shù),則Vector的默認(rèn)容量大小是10。

? ? ?·當(dāng)Vector容量不足以容納全部元素時(shí),Vector的容量會(huì)增加。若容量增加系數(shù) >0,則將容量的值增加“容量增加系數(shù)”;否則,將容量大小增加一倍。

? ? ?·Vector的克隆函數(shù),即是將全部元素克隆到一個(gè)數(shù)組中。

2.5 Stack棧

? ? (1)后進(jìn)先出(LIFO)的容器,是限制插入和刪除只能在一個(gè)位置上進(jìn)行的

? ? (2)LinkedList作為底層實(shí)現(xiàn)。

? ? (3)常用方法:

? ? ? ? · push(Object o)? ? ? ? ? ? ? ? ? ? ? ? · pop()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? · peek()

????(4)常見應(yīng)用:

? ? ? ? ? ? · 后綴表達(dá)式

2.6 Set的實(shí)現(xiàn)

2.6.1 HashSet

(1)最快的獲取元素的方式

(2)利用HashMap的Key存儲(chǔ)

(3)判斷重復(fù)元素原理:

? ? ? ? · 利用hashCode()和equals()方法。先計(jì)算加入對象的hashcode值來判斷加入的位置,同時(shí)與其他對象的hashcode值比較,如果沒有相同的hashcode,則假設(shè)對象沒有重復(fù)出現(xiàn)。若hashcode相同,則通過equals方法價(jià)差hashcode相等的對象是否真的相同,若相同,則插入操作不成功;若不同,則重新散列。

? ? ? ? · equals()方法被覆蓋,則hashCode()方法也必須被覆蓋。原因:
? ? ? ? ? ? ? ? · 兩個(gè)對象相等,hashcode值一定相同。
? ? ? ? ? ? ? ? · 兩個(gè)對象相等,equals()方法放回true。
? ? ? ? ? ? ? ? · 相同hashcode值,對象不一定相等。

2.6.2 TreeSet

(1)具有有序的存儲(chǔ)順序,按照比較結(jié)果的升序保存對象

(2)利用紅黑樹結(jié)構(gòu)實(shí)現(xiàn)

2.6.3 LinkedHashSet

(1)按照添加的順序保存對象

(2)使用鏈表來維護(hù)元素的插入順序

2.7 Map的實(shí)現(xiàn)

2.7.1 HashMap

2.7.1.1 概念

(1)提供最快的查找技術(shù)

(2)基于散列表實(shí)現(xiàn)

(3)線程不安全

(4)hash()方法

static final int hash(Object key) {

????int h;

????// key.hashCode():返回散列值也就是hashcode

????// ^ :按位異或

????// >>>:?符號(hào)右移,忽略符號(hào)位,空位都以0補(bǔ)?

????return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

? ? · HashMap通過key的hashCode經(jīng)過擾動(dòng)函數(shù)處理過后得到hash值

? ? · 然后通過(n - 1) & hash判斷當(dāng)前元素存放的位置,n為數(shù)組的長度。

? ? · 判斷該元素與存入的元素的hash值和key是否相同,相同則直接覆蓋,不相同就通過“拉鏈法”解決沖突。

2.7.1.2 底層數(shù)據(jù)結(jié)構(gòu)

(1)JDK1.8之前,使用數(shù)組+鏈表

? ? ? ? 數(shù)組中存儲(chǔ)Node<K,V>(implements Map.Entry<K,V>)。數(shù)組初始大小為16.

圖2-1 HashMap1.8之前

(2)JDK1.8之后,使用數(shù)組+鏈表+紅黑樹,當(dāng)鏈表的長度大于閾值(默認(rèn)8)時(shí) ,變?yōu)榧t黑樹

圖2-2 HashMap1.8之后

2.7.1.3 rehash擴(kuò)容機(jī)制

(1)哈希桶數(shù)組table的長度length大小必須為2的n次方(一定是合數(shù)),這是一種非常規(guī)的設(shè)計(jì),常規(guī)的設(shè)計(jì)是把桶的大小設(shè)計(jì)為素?cái)?shù)。相對來說素?cái)?shù)導(dǎo)致沖突的概率要小于合數(shù)

為什么要是2的n次方:取余(%)操作中,如果除數(shù)是2的冪次則等價(jià)于其除數(shù)減一的與(
&)操作,即hash%length == hash & (length - 1)。采用二進(jìn)制的位操作后,相對于%能提高運(yùn)算效率。

(2)擴(kuò)容條件

????int threshold; // 所能容納的key-value對極限

? ? final float loadFactor;? ? // 負(fù)載因子

? ? int modCount;?

? ? int size;

????首先,Node[] table的初始化長度length(默認(rèn)值是16),Load factor為負(fù)載因子(默認(rèn)值是0.75),threshold是HashMap所能容納的最大數(shù)據(jù)量的Node(鍵值對)個(gè)數(shù)。threshold = length * Load factor。也就是說,在數(shù)組定義好長度之后,負(fù)載因子越大,所能容納的鍵值對個(gè)數(shù)越多。

if (++size > threshold)

? ? ? ? ?resize();

當(dāng)大于閾值threshold 時(shí),進(jìn)行擴(kuò)容。

(3)rehash過程

? ? · 數(shù)組大小擴(kuò)容為原來的2倍。

? ? · 再散列到新數(shù)組。

(4)弊端

? ? 多線程操作可能導(dǎo)致形成循環(huán)鏈表(rehash過程)。參考https://zhuanlan.zhihu.com/p/21673805

參考:https://mp.weixin.qq.com/s?src=11&timestamp=1613981827&ver=2905&signature=vByozoJ33qW-bwQ1g-YMiVEpM7Y2B8Woya-sfEgileo2AigmyECAdZFyCtdLUoDtorLq3N8w0kx-WrN9ZRD4BLY6P21gLKQxf*GS4ZSUuWh0rsKKvQ45*dK*pm0NWeKF&new=1

2.7.2 TreeMap

(1)按照比較結(jié)果的升序保存鍵值

(2)基于紅黑樹(自平衡的排序二叉樹)實(shí)現(xiàn),次序由Comparable或者Comparator決定

2.7.3 LinkedHashMap

(1)按照插入順序保存鍵值,同時(shí)保留HashMap的查詢速度

(2)使用鏈表維護(hù)內(nèi)部順序。

(3)采用基于訪問的最近最少使用(LRU)算法,沒有被訪問過的元素就會(huì)出現(xiàn)在隊(duì)列的前面。

2.7.4 HashTable

(1)線程安全,內(nèi)部的方法基本都是經(jīng)過synchronized修飾,其他使用與HashMap類似。

(2)與concurrentHashMap相比,HashTable使用全表鎖

圖2-3 HashTable

2.7.5 ConcurrentHashMap

? ? 與HashMap相比,線程安全,適合并發(fā)環(huán)境。

(1)JDK1.7 分段鎖

? ? ? ? 對整個(gè)通數(shù)組進(jìn)行分割分段(Segment),多線程訪問容器不同段數(shù)據(jù)時(shí),不會(huì)存在鎖競爭,提高并發(fā)訪問效率。

圖2-4 ConcurrentHashMap1.7

(2)JDK1.8 synchronized + CAS

? ? ? ? 看起來是一個(gè)優(yōu)化過且線程安全的HashMap。synchronized只鎖定當(dāng)前鏈表或紅黑樹的首節(jié)點(diǎn)。

圖2-5 ConcurrentHashMap1.8

2.8 Queue

????先進(jìn)先出(FIFO)的容器,在一端進(jìn)行插入而在另一端進(jìn)行刪除的。

2.8.1 實(shí)現(xiàn)方式

(1)Deque接口,雙端隊(duì)列,底層實(shí)現(xiàn)可以選擇LinkedList。

(2)LinkedList

(3)PriorityQueue

? ? ? ? ? ? 優(yōu)先級(jí)隊(duì)列(堆),用Comparator對象修改排序順序,默認(rèn)為最小堆。

2.8.2 分類

(1)單隊(duì)列,存在“假溢出”問題

(2)循環(huán)隊(duì)列

2.9 比較器

2.9.1 Comparable

????來自java.lang包,使用comparaTo(Object obj)方法排序。

????Comparable是排序接口。若一個(gè)類實(shí)現(xiàn)了Comparable接口,就意味著該類支持排序。實(shí)現(xiàn)了Comparable接口的類的對象的列表或數(shù)組可以通過Collections.sort或Arrays.sort進(jìn)行自動(dòng)排序。

????此外,實(shí)現(xiàn)此接口的對象可以用作有序映射中的鍵或有序集合中的集合,無需指定比較器。

public class Person implements Comparable<Person>{

????@Override

? ? publicint compareTo(Person p)

? ? {

? ? ? ? return this.age-p.getAge();

? ? }

}

? ? 上述demo表示按照從小到大的年紀(jì)排序?qū)ο蟆?/p>

2.9.2 Comparator

? ? 來自java.util包,使用compare(Object obj1, Object obj2)方法排序。

????Comparator是比較接口,我們?nèi)绻枰刂颇硞€(gè)類的次序,而該類本身不支持排序(即沒有實(shí)現(xiàn)Comparable接口)。

? ? int compare(T o1, T o2) 是“比較o1和o2的大小”。返回“負(fù)數(shù)”,意味著“o1比o2小”;返回“零”,意味著“o1等于o2”;返回“正數(shù)”,意味著“o1大于o2”.

public class PersonCompartor implements Comparator{

? ? @Override

? ? publicint compare(Person o1, Person o2)

? ? {

? ? ? ? return o1.getAge()-o2.getAge();//從小到大排序

? ? }

}

Arrays.sort(people,new PersonCompartor());

// 定制排序的?法

Collections.sort(arrayList, new Comparator<Integer>() {
?????@Override
?????public int compare(Integer o1, Integer o2) {
?????????return o2.compareTo(o1); //從大到小排序
?????????}
? });?

注意:上面demo的compareTo方法,在String類和8種基本類型的包裝類中都含有,按字典序或自然順序排序。

2.10 工具類Collections和Arrays

2.10.1 Arrays

????在java.util中有一個(gè)Arrays類,此類包含用于操縱數(shù)組的各種方法,例如:二分查找(binarySearch)、拷貝操作(copyOf)、比較(equals)、填充(fill)、排序(sort)等,功能十分強(qiáng)大。

排序 :sort() 默認(rèn)從小到大排序

查找 :binarySearch()

比較: equals

填充 :fill(int[], int),可以用作批量初始化

轉(zhuǎn)列表: asList(int, int, int) 參數(shù)用逗號(hào)隔開

哈希:hashCode()

轉(zhuǎn)字符串 :toString()

拷貝:copyOfRange(int[], int from, int to)


2.10.2 Collections

(1)排序

void reverse(List list)//反轉(zhuǎn)

void shuffle(List list)//隨機(jī)排序

void sort(List list)//按自然排序的升序排序

void sort(List list, Comparator c)//定制排序,由Comparator控制排序邏輯

void swap(List list, int i , int j)//交換兩個(gè)索引位置的元素

void rotate(List list, int distance)//旋轉(zhuǎn)。當(dāng)distance為正數(shù)時(shí),將list后distance個(gè)元素整體移到前面。當(dāng)distance為負(fù)數(shù)時(shí),將 list的前distance個(gè)元素整體移到后面。

(2)查找替換

int binarySearch(List list, Object key)//對List進(jìn)行二分查找,返回索引,注意List必須是有序的

int max(Collection coll)//根據(jù)元素的自然順序,返回最大的元素。 類比int min(Collection coll)

int max(Collection coll, Comparator c)//根據(jù)定制排序,返回最大元素,排序規(guī)則由Comparatator類控制。類比int min(Collection coll, Comparator c)

void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素。

int frequency(Collection c, Object o)//統(tǒng)計(jì)元素出現(xiàn)次數(shù)

int indexOfSubList(List list, List target)//統(tǒng)計(jì)targe在list中第一次出現(xiàn)的索引,找不到則返回-1,類比int lastIndexOfSubList(List source, list target).

boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替換舊元素


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容