Java性能优化方面的程序优化知识点归纳,希望对你有所帮助
常用的程序設(shè)計優(yōu)化技巧:
1、字符串優(yōu)化處理
(1)String 類的特點:不變性、針對常量池的優(yōu)化( String.intern() 方法的意義)
(2)subString 方法的內(nèi)存泄漏 :
(3)字符串分割和查找不要使用 split 函數(shù),效率低,而是使用 StringTokenizer 或者 indexOf結(jié)合 subString() 函數(shù)完成分割。
(4)用 charAt ()方法代替 startWith ()方法。
(5)對于靜態(tài)字符串或者變量字符串的連接操作, Java 在編譯的時候會進(jìn)行徹底的優(yōu)化,將多個連接操作的字符串在編譯時合成一個單獨的字符串,而不是生成大量的 String 實例。只生成一個對象。
(6)在無需考慮線程安全情況下盡量使用 StringBuilder 。
(7)StringBuffer 和 StringBuilder 初始化的時候都可以設(shè)置一個初始值,默認(rèn)是 16B 。如果字符串的長度大于 16B 的時候,則需要進(jìn)行擴(kuò)容。擴(kuò)容策略是將原有的容量大小翻倍,以新的容量申請內(nèi)存空間,建立 char 數(shù)組,然后將數(shù)組中的內(nèi)容復(fù)制到這個新的數(shù)組中,使用 Arrays.copyOf() 函數(shù)。因此,如果能預(yù)先評估 StringBuilder 的大小,則可以節(jié)省這些復(fù)制操作,從而提高系統(tǒng)的性能。
2、List 接口
( 1 ) ArrayList 和 Vector 的區(qū)別:它們幾乎使用了相同的算法,它們的唯一區(qū)別是對多線程的支持。 ArrayList 是不安全的,而 Vector 是線程安全的。
( 2 ) LinkedList 和 ArrayList 的區(qū)別:
|---1 、 linkedList 采用鏈表實現(xiàn),適合于數(shù)據(jù)刪除和插入非常頻繁的情況,不適合隨機(jī)訪問。
|---2 、 ArrayList 采用數(shù)組實現(xiàn),適用于隨機(jī)查找和順序讀的情況,不適合刪除和插 入數(shù)據(jù)非常頻繁的場景。
(3)基于數(shù)組的 List 都會有一個容量參數(shù)。當(dāng) ArrayList 所存儲的元素容量超過其已有大小的時候就會進(jìn)行擴(kuò)容,數(shù)組的擴(kuò)容會導(dǎo)致整個數(shù)組進(jìn)行一次內(nèi)存復(fù)制。因此合理的數(shù)組大小會減小數(shù)組擴(kuò)容的次數(shù)從而提高系統(tǒng)性能。
(4)遍歷列表的時候盡量使用迭代器,速度快。
2、Map 接口:
(1)HashMap 的實現(xiàn)原理:簡單的說, HashMap 就是將 key 做 hash 算法,然后將 hash 值映射到內(nèi)存地址,直接取得 key 所對應(yīng)的數(shù)據(jù)。在 HashMap 中,底層數(shù)據(jù)結(jié)構(gòu)使用的是數(shù)組,所謂的內(nèi)存地址指的是數(shù)組的下標(biāo)索引。
(2)容量參數(shù)與擴(kuò)容:默認(rèn)情況下, hashmap 的初始容量為 16 ,負(fù)載因子為 0.75 ,也就是說當(dāng) hashmap 的實際容量達(dá)到了初始容量 * 負(fù)載因子( hashmap 內(nèi)部維護(hù)的一個 threshold 值)的時候, hashmap 就會進(jìn)行擴(kuò)容。在擴(kuò)容時,會遍歷整個 hashmap ,因此應(yīng)該設(shè)置合理的初始大小和負(fù)載因子,可以減小 hashmap 擴(kuò)容的次數(shù)。
(3)LinkedHashMap-- 有序的 HashMap : HashMap 的最大缺點是其無序性,被存入到 Hashmap 中的元素,在遍歷 HashMap 的時候,其輸出不一定按照輸入的順序,而是 HashMap 會根據(jù) hash 算法設(shè)定一個查找高效的順序。如果希望保存輸入順序,則需要使用 LinkedHashMap 。LinkedHashmap 在內(nèi)部又增加了一個鏈表,用于保存元素的順序。
(4)LinkedList 可以提供兩種類型的順序:一個是元素插入時候的順序,一個是最近訪問的順序。注意: LinkedHashMap 在迭代過程中,如果設(shè)置為按照最后訪問時間進(jìn)行排序,即:每當(dāng)使用 get() 方法訪問某個元素時,該元素便會移動到鏈表的尾端。但是這個時候會出現(xiàn)異常,因此, LinkedHashMap 工作在這種模式的時候,不能在迭代器中使用 get() 操作。
(5)關(guān)于 ConcurrentModificationException :該異常一般會在集合迭代過程中被修改時拋出。因此,不要在迭代器模式中修改集合的結(jié)構(gòu)。這個特性適合于所有的集合類,包括 HashMap 、 Vector 、 ArrayList 等。
(6)TreeMap-- 如果要對元素進(jìn)行排序,則使用 TreeMap 對 key 實現(xiàn)自定義排序,有兩種方式:在 TreeMap 的構(gòu)造函數(shù)中注入一個 Comparator 或者使用一個實現(xiàn)了 Comparable 的 key 。
(7)如果需要將排序功能加入 HashMap ,最好是使用 Treemap 而不是在應(yīng)用程序自定義排序。
(8)HashMap 基于 Hash 表實現(xiàn), TreeMap 基于紅黑樹實現(xiàn)。
3 、 Map 和 Set 的關(guān)系:
( 1 )所有 Set 的實現(xiàn)都只是對應(yīng)的 Map 的一種封裝,其內(nèi)部維護(hù)一個 Map 對象。即: Set只是相應(yīng)的 Map 的 Value 是一種特殊的表現(xiàn)形式的一種特例。
( 2 ) Set 主要有三種實現(xiàn)類: HashSet 、 LinkedHashSet 、 TreeSet 。其中 HashSet 是基于 Hash 的快速元素插入,元素之間無序。 LinkedHashSet 同時維護(hù)著元素插入順序,遍歷集合的時候,總是按照先進(jìn)先出的順序排序。 TreeSet 是基于紅黑樹的實現(xiàn),有著高效的基于元素 Key 的排序算法。
4 、優(yōu)化集合訪問代碼:
( 1 )、分離循環(huán)中被重復(fù)調(diào)用的代碼:例如, for 循環(huán)中使用集合的 size() 函數(shù),則不應(yīng)該把這個函數(shù)的調(diào)用放到循環(huán)中,而是放到循環(huán)外邊、
( 2 )、省略相同的操作:
5 、 RandomAccess 接口:通過 RandomAccess 可知道 List 是否支持隨機(jī)快速訪問。同時,如果應(yīng)用程序需要通過索引下標(biāo)對 List 做隨機(jī)訪問,盡量 buyaoshiyongLinkedList , ArrayList 或者 Vector 可以。
6 、 JavaNIO 的特性:
1 、為所有的原始類型提供 Buffer 支持。
2 、使用 Java.nio.charset.Charset 作為字符編碼解碼解決方案。
3 、增加通道抽象代替原有的 IO 流抽象。
4 、支持鎖和內(nèi)存映射文件的文件訪問接口。
5 、提供基于 Selector 的異步網(wǎng)絡(luò) IO 。
7 、 Java 中 NIO 的使用。 Channel 是一個雙向通道,即可讀也可寫。應(yīng)用程序不能直接操作 Channel ,必須借助于 Buffer 。例如讀數(shù)據(jù)的時候,必須把數(shù)據(jù)從通道讀入到緩沖區(qū),然后在緩沖區(qū)中進(jìn)行讀取。以文件讀取為例,首先通過文件輸入流獲得文件通道,然后把文件通道的內(nèi)容讀入到緩沖區(qū)中,然后就可以對緩沖區(qū)操作。
8 、 Buffer 的基本原理:
1 、 Buffer 的創(chuàng)建: Buffer 的靜態(tài) allocate(int size) 方法或者 Buffer.wrap(byte[]src) 。
2 、 Buffer 的工作原理:三個變量: position ,代表當(dāng)前緩沖區(qū)的位置,寫緩沖區(qū)的時候,將從 position 的下一個位置寫數(shù)據(jù)。 Capacity ,代表緩沖區(qū)的總?cè)萘可舷蕖?Limit ,緩沖區(qū)的實際上限,也就是說,讀數(shù)據(jù)的時候,數(shù)據(jù)即是從 position 到 limit 之間的數(shù)據(jù)
3 、 flip 操作: limit=position,position=0, 一般是在讀寫切換的時候使用。寫完數(shù)據(jù)之后,需要限定下有效數(shù)據(jù)范圍,才能讀數(shù)據(jù);
4 、 clear 操作: position-0 , limit=capacity. 。為重新寫入緩沖區(qū)做準(zhǔn)備。
5 、 rewind 操作: position=0 ,為讀取緩沖區(qū)中有效數(shù)據(jù)做準(zhǔn)備,一半 limit 已經(jīng)被合理設(shè)置。
9 、讀寫緩沖區(qū):
1 、 public byte get() :順序讀取緩沖區(qū)的一個字節(jié), position 會加一
2 、 public Buffer get(byte[]dst): 將緩沖區(qū)中的數(shù)據(jù)讀入到數(shù)組 dst 中,并適當(dāng)?shù)囊苿?position
3 、 public byte get(int index) :得到第 index 個字節(jié),但不移動 posoiion
4 、 public ByteBuffer put(byte b) :將字節(jié) b 放入到緩沖區(qū)中,并移動 position
5 、 public ByteBuffer put(int index,byte b) :將字節(jié) b 放到緩沖區(qū)的 index 位位置
6 、 pubglic final ByteBuffer(byte[]src) :將字節(jié)數(shù)組 src 放到緩沖區(qū)中。
10 、標(biāo)志緩沖區(qū):類似于一個書簽的功能,在數(shù)據(jù)的處理過程中,可隨時記錄當(dāng)前位置。然后在任意時刻,回到這個位置。 Mark 用于記錄當(dāng)前位置, reset 用于恢復(fù)到 mark 所在的位置、
11 、復(fù)制緩沖區(qū):使用 Buffer 的 duplicate 方法可以復(fù)制一個緩沖區(qū),副本緩沖區(qū)和原緩沖區(qū)共享一份空間但是有有著獨立的 position 、 capacity 和 limit 值。
20 、緩沖區(qū)分片:緩沖區(qū)分片使用 slice 方法實現(xiàn)。它將在現(xiàn)有的緩沖區(qū)中,創(chuàng)建的子緩沖區(qū)。子緩沖區(qū)和父緩沖區(qū)共享數(shù)據(jù)。這個方法有助于將系統(tǒng)模塊化。緩沖區(qū)切片可以將一個大緩沖區(qū)進(jìn)行分割處理,得到的子緩沖區(qū)都具有緩沖的緩沖區(qū)模型結(jié)構(gòu);因此。這個操作有助于系統(tǒng)的模塊化。
12 、只讀緩沖區(qū):只讀緩沖區(qū)可以保證核心數(shù)據(jù)的安全,如果不希望數(shù)據(jù)被隨意篡改,返回一個只讀緩沖區(qū)是很有幫助的。
13 、文件映射到內(nèi)存: NIO 提供了一種將文件映射到內(nèi)存的方法進(jìn)行 IO 操作,這種方法比基于流 IO 快很多。這個操作主要由 FileChanne.map() 操作。使用文件內(nèi)存的方式,將文本通過 FileChannel 映射到內(nèi)存中。然后從內(nèi)存中讀取數(shù)據(jù)。同時,通過修改 Buffer, 將對內(nèi)存中數(shù)據(jù)的修改寫到對應(yīng)的硬盤文件中。
14 、處理結(jié)構(gòu)化數(shù)據(jù):散射和聚集。散射就是將數(shù)據(jù)讀入到一組 bytebuffer 中,而聚集正好相反。通過 ScatteringByteChannel 和 GatheringByteChannel 可以簡化對結(jié)構(gòu)數(shù)據(jù)的操作。
15 、直接內(nèi)存訪問: DirectBuffer 直接分配在物理內(nèi)存中,并不占用對空間,因此也不受對空間限制。 DirectBuffer 的讀寫操作比普通 Buffer 塊,因為 DirectBuffer 直接操縱的就是內(nèi)核緩沖區(qū)。
16 、引用類型:強(qiáng)、軟、若、虛四種引用類型。
WeakHashMap :是弱引用的一中典型應(yīng)用,它使用弱引用作為內(nèi)部數(shù)據(jù)的存儲方案。可以作為簡單的緩存表解決方案。
如果在系統(tǒng)中,需要一張很大的 Map 表, Map 中的表項作為緩存之用。這也意味著即使沒能從該 Map 中取得相應(yīng)地數(shù)據(jù),系統(tǒng)也可以通過選項方案獲取這些數(shù)據(jù),雖然這樣會消耗更多的時間,但是不影響系統(tǒng)的正常運行。這個時候,使用 WeakHashMap 是最合適的。因為 WeakHashMap 會在系統(tǒng)內(nèi)存范圍內(nèi),保存所有表項,而一旦內(nèi)存不夠,在 GC 時,沒有被引用的又會很快被清除掉,避免系統(tǒng)內(nèi)存溢出。
17 、有助于改善系統(tǒng)性能的技巧:
1 、慎用異常: for 循環(huán)中使用 try-catch 會大大降低系統(tǒng)性能
2 、使用局部變量:局部變量的訪問速度遠(yuǎn)遠(yuǎn)高于類的靜態(tài)變量的訪問速度,因為類的 變量是存在在堆空間中的。
3 、位運算代替乘除法:右移代表除以二、左移代表乘以二。
4 、有的時候考慮是否可以使用數(shù)組代替位運算。
5 、一維數(shù)組代替二維數(shù)組。
6 、提取表達(dá)式:盡可能讓程序少做重復(fù)的計算,尤其要關(guān)注在循環(huán)體的代碼,從循環(huán)提中提取重復(fù)的代碼可以有效的提升系統(tǒng)性能。
為了讓學(xué)習(xí)變得輕松、高效,今天給大家免費分享一套Java入門教學(xué)資源。幫助大家在成為Java架構(gòu)師的道路上披荊斬棘。需要入門的資料歡迎加入學(xué)習(xí)交流群:9285,05736
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Java性能优化方面的程序优化知识点归纳,希望对你有所帮助的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux相关英文书记,Linux常用软
- 下一篇: php常用函数、算法,PHP常用函数和常