—舉例(學生排課)—
正常思路的處理方法和優化過后的處理方法:
比如說給學生排課。學生和課程是一個多對多的關系。
按照正常的邏輯 應該有一個關聯表來維護 兩者之間的關系。
現在,添加一個約束條件用于校驗。如:張三上學期學過的課程,在排課的時候不應該再排這種課程。
所以需要出現一個約束表(即:歷史成績表)。
即:學生選課表,需要學生成績表作為約束。
—方案一:正常處理方式—
當一個學生進行再次選課的時候。需要查詢學生選課表看是否已經存在。
即有如下校驗:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//查詢 學生code和課程code分別為 a 和 b的數據是否存在 //list集合中存放 學生選課記錄全部的數據 list<studentrecordentity> liststudentrecord=service.findall(); //查詢數據,看是否已經存在 studentrecordentity ensr=liststudentrecord.find(s=>s.學生code==a && s.課程code==b); if (ensr== null ){ //學生沒有選該課程 //.... } else { //學生已經選過該課程 //.... } |
對于上面這種代碼的寫法,非常的簡練。而且也非常易懂。
首先,假設有5000個學生,100門課程。那么對于學生選課的數據集中,數據量將是5000*100.數據量會是十萬級別的數量級。
在十萬條數據中,查詢學生=a課程=b的一條記錄。執行的效率會很低。因為find方法的查詢也就是where查詢,即通過遍歷數據集合來查找。
所以,使用上面的代碼。在數據量逐漸增長的過程中,程序的執行效率會大幅度下降。
ps:數據量增長,在該例子中并不太適合。例子可能不太恰當。總之,大概就是這個意思。)
—方案二:使用內存進行優化效率—
這種做法,需要消耗內存?;蛘哒f把校驗的工作向前做(數據的初始化,在部署系統的過程中進行)。即:在頁面加載的時候數據只調用提供的public方法進行校驗。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
//學生code 到 數組索引 private dictionary<string, int > _dicstudentcodetoarrayindex; //課程code 到 數據索引 private dictionary<string, int > _diccoursecodetoarrayindex; //所有學生 list<studententity> liststudent=service.findallstudent(); //所有課程 list<courseentity> listcourse=service.findallcourse(); //所有 學生選課記錄 list<studentcourseentity> liststudentrecord=service.finall(); private int [,] _connstudentrecord= new int [liststudent.count,listcourse.count]; //構造 學生、課程的 數組 用于快速查找字典索引 private void generatedic(){ for ( int i= 0 ; i<liststudent.count; i++) _dicstudentcodetoarrayindex.add(liststudent[i].code,i) } for ( int i= 0 ; i<listcourse.count; i++){ _diccoursecodetoarrayindex.add(listcourse[i].code,i) } } //構造學生選課 匹配的 二維數組。 1表示 學生已選該課程 private void generatearray(){ foreach(studentrecordentity sre in liststudentrecord){ int x=_dicstudentcodetoarrayindex[sre.學生code]; int y=diccoursecodetoarrayindex[sre.課程code]; connstudentrecord[x,y]= 1 ; } } //對外公開的方法:根據學生code 和課程code 查詢 選課記錄是否存在 /// <returns>返回1 表示存在。返回0表示不存在</returns> public void verifyrecordbystudentcodeandcoursecode(string pstudentcode,string pcoursecode){ int x=_dicstudentcodetoarrayindex[pstudentcode]; int y=_diccoursecodetoarrayindex[pcoursecode]; return connstudentrecord[x,y]; } |
—性能分析—
分析一下第二種方案的表象。
1、方法很多。
2、使用的變量很多。
首先要說一下。該優化的目的,是提高學生在選課的時候,所出現的卡頓現象(校驗數據量大)。
分別對以上兩種方案進行分析:
假設學生為n,課程為m
第一種方案:
時間復雜度很容易計算第一種方案最小為o(nm)
第二種方案:
1、代碼多。但是給用戶提供的只有一個verifyrecordbystudentcodeandcoursecode方法。
2、變量多,因為該方案就是要使用內存提高效率的。
這個方法執行流程:1、在dictionary中使用code找index2、使用index查詢數組。
第一步中,dictionary中查詢是使用的hash查找算法。時間復雜度為o(lgn)時間比較快。第二步,時間復雜度為o(1),因為數組是連續的使用索引會直接查找對應的地址。
所以,使用第二種方案進行校驗,第二種方案時間復雜度為o(lgn+lgm)
—總結—
通過上面的分析,可以看出,內存的付出是可以提高程序的執行效率的。以上只是一個例子,優化的好壞取決于使用的數據結構。
以上就是本文關于java性能優化之數據結構實例代碼的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
原文鏈接:http://blog.csdn.net/lee_sire/article/details/54024091