- 相關(guān)推薦
Java編程性能優(yōu)化技巧分享
針對大家的提問Java編程性能優(yōu)化技巧有哪些,小編特意收集了以下的解答內(nèi)容,希望對您有所幫助!更多內(nèi)容請關(guān)注應(yīng)屆畢業(yè)生考試網(wǎng)!
1、字符串優(yōu)化處理
(1)String類的特點(diǎn):不變性、針對常量池的優(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)化,將多個連接操作的字符串在編譯時合成一個單獨(dú)的字符串,而不是生成大量的String實(shí)例。只生成一個對象。
(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采用鏈表實(shí)現(xiàn),適合于數(shù)據(jù)刪除和插入非常頻繁的情況,不適合隨機(jī)訪問。
|---2、ArrayList采用數(shù)組實(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的實(shí)現(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的實(shí)際容量達(dá)到了初始容量*負(fù)載因子(hashmap內(nèi)部維護(hù)的一個threshold值)的時候,hashmap就會進(jìn)行擴(kuò)容。在擴(kuò)容時,會遍歷整個hashmap,因此應(yīng)該設(shè)置合理的初始大小和負(fù)載因子,可以減小hashmap擴(kuò)容的次數(shù)。
(3)LinkedHashMap--有序的HashMap:HashMap的最大缺點(diǎn)是其無序性,被存入到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實(shí)現(xiàn)自定義排序,有兩種方式:在TreeMap的構(gòu)造函數(shù)中注入一個Comparator或者使用一個實(shí)現(xiàn)了Comparable的key。
(7)如果需要將排序功能加入HashMap,最好是使用Treemap而不是在應(yīng)用程序自定義排序。
(8)HashMap基于Hash表實(shí)現(xiàn),TreeMap基于紅黑樹實(shí)現(xiàn)。
3、Map和Set的關(guān)系:
(1)所有Set的實(shí)現(xiàn)都只是對應(yīng)的Map的一種封裝,其內(nèi)部維護(hù)一個Map對象。即:Set只是相應(yīng)的Map的Value是一種特殊的表現(xiàn)形式的一種特例。
(2)Set主要有三種實(shí)現(xiàn)類:HashSet、LinkedHashSet、TreeSet。其中HashSet是基于Hash的快速元素插入,元素之間無序。LinkedHashSet同時維護(hù)著元素插入順序,遍歷集合的時候,總是按照先進(jìn)先出的順序排序。TreeSet是基于紅黑樹的實(shí)現(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è)萘可舷蕖imit,緩沖區(qū)的實(shí)際上限,也就是說,讀數(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ù)囊苿觩osition
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ū)共享一份空間但是有有著獨(dú)立的position、capacity和limit值。
20、緩沖區(qū)分片:緩沖區(qū)分片使用slice方法實(shí)現(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塊,因?yàn)镈irectBuffer直接操縱的就是內(nèi)核緩沖區(qū)。
16、引用類型:強(qiáng)、軟、若、虛四種引用類型。
WeakHashMap:是弱引用的一中典型應(yīng)用,它使用弱引用作為內(nèi)部數(shù)據(jù)的存儲方案。可以作為簡單的緩存表解決方案。如果在系統(tǒng)中,需要一張很大的Map表,Map中的表項(xiàng)作為緩存之用。這也意味著即使沒能從該Map中取得相應(yīng)地?cái)?shù)據(jù),系統(tǒng)也可以通過選項(xiàng)方案獲取這些數(shù)據(jù),雖然這樣會消耗更多的時間,但是不影響系統(tǒng)的正常運(yùn)行。這個時候,使用WeakHashMap是最合適的。因?yàn)閃eakHashMap會在系統(tǒng)內(nèi)存范圍內(nèi),保存所有表項(xiàng),而一旦內(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)變量的訪問速度,因?yàn)轭惖淖兞渴谴嬖谠诙芽臻g中的。
3、位運(yùn)算代替乘除法:右移代表除以二、左移代表乘以二。
4、有的時候考慮是否可以使用數(shù)組代替位運(yùn)算。
5、一維數(shù)組代替二維數(shù)組。
6、提取表達(dá)式:盡可能讓程序少做重復(fù)的計(jì)算,尤其要關(guān)注在循環(huán)體的代碼,從循環(huán)提中提取重復(fù)的代碼可以有效的提升系統(tǒng)性能。
【Java編程性能優(yōu)化技巧分享】相關(guān)文章:
Java性能優(yōu)化技巧大全07-12
java編程基礎(chǔ)07-26
java教程之Java編程基礎(chǔ)09-12
java工程師面試技巧分享05-29
Java語言的編程特點(diǎn)03-18
Java編程學(xué)習(xí)示例07-31
java面向接口編程08-01
java并發(fā)編程參考10-30
java編程規(guī)范介紹07-10
java面向?qū)ο缶幊讨v解06-18