10億個字符串的排序問題

一、問題描述

有一個大文件,里面有十億個字符串,亂序的,要求將這些字符串以字典的順序排好序

?

二、解決思路

? ? 將大文件切割成小文件,每個小文件內歸并排序;

? ? 對所有的小文件進行歸并排序——多重歸并排序

?

三、解決方案

3.1?模擬產生10億個隨機字符

public static void generateDate() throws IOException {BufferedWriter writer = new BufferedWriter(new FileWriter(ORIGINALPATH));Random random = new Random();StringBuffer buffer = new StringBuffer("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");int range = buffer.length();int length = 1;for (int i = 0; i < BIGDATALENGTH; i++) {StringBuffer sb = new StringBuffer();length = random.nextInt(20)+1;//System.out.println("length--->"+length);for (int j = 0; j < length; j++) {//System.out.println("j--->"+j);sb.append(buffer.charAt(random.nextInt(range)));}System.out.println("sb---->"+sb);writer.write(sb.toString() + "
");}writer.close();
}

?

3.2?對大文件進行切割

/**

}

/*** 將原始數據分成幾塊 并排序 再保存到臨時文件* @throws IOException*/
public static void splitData() throws IOException {@SuppressWarnings("resource")BufferedReader br = new BufferedReader(new FileReader(ORIGINALPATH));tempFiles = new File[BIGDATALENGTH / TEMPFILELENGTH];//將會產生的臨時文件列表for (int i = 0; i < tempFiles.length; i++) {tempFiles[i] = new File(TEMPFILEPATH + "TempFile" + i + ".txt");BufferedWriter writer = new BufferedWriter(new FileWriter(tempFiles[i]));HashMap<Integer,String> hashMap = new HashMap<Integer,String>();//未排序//每次讀出TEMPFILELENGTH個文件 保存到smallLine中for (int j = 1; j <= TEMPFILELENGTH; j++) {String text = null;if ((text = br.readLine()) != null) {hashMap.put(j, text);}}hashMap = MergeSort.sort(hashMap);for(int k=1; k<=TEMPFILELENGTH; k++){writer.write(String.valueOf(hashMap.get(k))+ System.getProperty("line.separator"));
//System.getProperty("line.separator")相當于}writer.close();}
}

?

3.3?對小文件進行遞歸歸并

?

/*** 多路歸并排序* @param files* @throws IOException*/
public static void multiWaysMergeSort(String[] files) throws IOException {System.out.println("歸并文件-----第 "+mergeSortCount+" 次-----");//當最后只有一個文件的時候 數據已經排序成功 直接復制保存到結果文件if (files.length == 1) {String lastFilePath = LASTFILEPATH + LASTFILENAME;copyFile(files[0], lastFilePath, false);//deleteFile(files[0]);return;}for (int i = 0; i < files.length; i+=2) {
//開始合并兩個相鄰的文件 所以一次跳兩個if (i == files.length - 1) {
//這時候已經只剩下最后一個文件了 不需要合并 本趟歸并結束renameFile(files[i], i);break;}//將br1 和 br2 寫入到WriteBufferedReader br1 = new BufferedReader(new FileReader(files[i]));BufferedReader br2 = new BufferedReader(new FileReader(files[i + 1]));BufferedWriter writer = new BufferedWriter(new FileWriter(TEMPFILEPATH + "last_" + mergeSortCount + "_" + i + ".txt"));String s1 = br1.readLine();String s2 = br2.readLine();while (s1 != null || s2 != null) {if (s1 != null && s2 != null) {
//都不為空 才有比較的必要int mergeResult = s1.compareTo(s2);if (mergeResult > 0) {//s1在s2后面writer.write(s2);writer.write(System.getProperty("line.separator"));s2 = br2.readLine();}if (mergeResult == 0) {//s1=s2writer.write(s1);								writer.write(System.getProperty("line.separator"));writer.write(s2);						writer.write(System.getProperty("line.separator"));
//						System.out.println("write time : " + writeTime++);s1 = br1.readLine();s2 = br2.readLine();}if (mergeResult < 0) {//s1在s2前面writer.write(s1);						writer.write(System.getProperty("line.separator"));s1 = br1.readLine();}}if (s1 == null && s2 != null) {writer.write(s2);writer.write(System.getProperty("line.separator"));s2 = br2.readLine();}if (s2 == null && s1 != null) {writer.write(s1);writer.write(System.getProperty("line.separator"));s1 = br1.readLine();}}br1.close();br2.close();
//			deleteFile(files[i]);
//			deleteFile(files[i + 1]);writer.close();}mergeSortCount++;multiWaysMergeSort(getTempFiles("last_" + (mergeSortCount-1) + "_"));
}

?

3.4?運行結果分析

①生成10億個隨機字符串,時間太久了,,字符串長度隨機在[1,20]之間時,文件大小大概在10.7?GB?(11,500,161,591?字節)

②?切割成小文件,小文件內歸并排序,每個文件內的數據100萬條時,隨機選取五個排序時間如下:

一共發生了410832612?次對比一共發生了?899862656?次交換執行時間為3545毫秒

一共發生了429506513?次對比一共發生了?940765504?次交換執行時間為3512毫秒

一共發生了448181315?次對比一共發生了?981668352?次交換執行時間為3497毫秒

一共發生了466856137?次對比一共發生了?1022571200?次交換執行時間為3497毫秒

一共發生了485530473?次對比一共發生了?1063474048?次交換執行時間為3981毫秒

總共1000個文件切割耗時為

切割小文件所用時間--->4341734ms--->4341.734s--->72.36m--->1.206h

③??小文件遞歸歸并,1000個文件,

共發生了10次歸并,

產生臨時文件總共1999個,

總大小為127.8?GB?(137,201,789,278?字節),

產生結果文件11.6?GB?(12,500,161,591?字節)

比源文件多了10億個字節......

總耗時為--->7374129ms--->7374.129s--->122.9m--->2.048h

不得不提的是,最后執行結果成功,也不枉我苦苦等待

四、相關技術

4.1?歸并排序

排序原理不多介紹,各種到處都有,如果一時不記得,看下面的原理圖。秒懂。


??

4.2?文件讀寫

本程序很重要的一點就是對于文件的讀寫,Buffer的文件讀寫可以很大程度的改善速率

寫操作:

BufferedWriter?writer?=?new?BufferedWriter(new?FileWriter(PATH));

writer.write("hhf ");

讀操作:

BufferedReader?br?=?new?BufferedReader(new?FileReader(PATH));

text?=?br.readLine()

?

五、關于優化

5.1分小文件時優化

前提:數據均勻,保證每個小文件大小不會超過內存的容量

處理:在分數據到小文件時,按字符串按首字母將其分到指定文件中,如A-C分配到1.txt,D-F分配到2.txt.......

優點:只需要小文件內數據排序,排序號后,即可將1.txt、2.txt、3.txt直接連接起來,極大的縮短了歸并時間,相當于把遞歸歸并變成了文件連接而已

缺點:前提不是很容易把握,若有一個小文件內的數據量大于內存的大小,則排序失敗,存在一定的風險

5.2小文件內排序時優化

前提:保證每個小文件內數據量比較不是特別的大

處理:將小文件內的數據進行快速排序

優點:快排的時間效率是高于歸并的

以下是測試數據

排序數量級??101000100000

歸并排序7ms71ms3331ms

快速排序6ms52msjava.lang.StackOverflowError

缺點:缺點已經顯示在測試數據內了,小文件內的數據量過大就可能導致當前線程的棧滿



原文鏈接

更多文章

轉載于:https://www.cnblogs.com/gyjWEB/p/5035763.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/256285.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/256285.shtml
英文地址,請注明出處:http://en.pswp.cn/news/256285.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MVC學習IIS的不同版本(一)

一&#xff1a;IIS5.0運行在進程InetInfo.exe中&#xff0c;該進程寄宿著一個名為World Wide Publishing Service&#xff08;W3VC&#xff09;的window服務。 W3VC的主要功能&#xff1a;包括HTTP請求的監聽、工作進程和配置管理 檢測到HTTP 請求時&#xff1a; 根據擴展名判斷…

Halcon中visualize_object_model_3d算子詳解

概念 此函數用于顯示3d模型。該函數功能很多,包括設置位姿,顏色,鼠標翻轉、縮放、平移,選擇和取消選擇目標,降低鼠標靈敏度,切換檢查模式等。 參數 visualize_object_model_3d( : : WindowHandle, ObjectModel3D, CamParam, PoseIn, GenParamName, GenParamValue, Tit…

random()模塊隨機函數的用法總結

random()是Python中生成隨機數的函數&#xff0c;是由random模塊控制&#xff0c;random()函數不能直接訪問&#xff0c;需要導入random 模塊&#xff0c;然后再通過相應的靜態對象調用該方法才能實現相應的功能 目錄 1. random.random() 2. random.uniform() 3. random.ra…

ansible命令應用示例

ansible命令應用示例 ping slave組ansible slave -m ping 用bruce 用戶以root 身份pingansible slave -m ping -u bruce --sudo 用bruce 用戶sudo 到batman 用戶pingansible slave -m ping -u bruce --sudo --sudo-user batman 給slave組安裝ftpan…

史上超全halcon常見3D算子匯總(一)

讀取3D模型 read_object_model_3d 此算子用于讀取3D對象。 read_object_model_3d( : : FileName, Scale, GenParamName, GenParamValue : ObjectModel3D, Status) FileName:文件名,halcon支持多種3d數據格式的讀取,包括 .off, .ply, .dxf, .om3, .obj, .stl等格式。 1).…

Python:常用模塊簡介(1)

sys模塊 >>> sys.platform #返回操作系統平臺名稱 win32 >>> sys.stdin #輸入相關 <open file <stdin>, mode r at 0x000000000337B030> >>> sys.stdout #輸出相關 <open file <stdout>, mode w at 0x000000000337…

【圖像處理】——Python實現圖像加噪(隨機噪聲、椒鹽噪聲、高斯噪聲等)

目錄 1、隨機噪聲 2、椒鹽噪聲 3、高斯噪聲 補充:numpy.clip函數 4、其他噪聲 1、隨機噪聲 隨機噪聲就是通過隨機函數在圖像上隨機地

100NED

將生活融入編程轉載于:https://www.cnblogs.com/nedhome/p/5036680.html

Windows10 VS2019下使用CMake3.20.1打開PCL1.11.0程序

安裝CMake 為什么要使用cmake cmake 是kitware 公司以及一些開源開發者在開發幾個工具套件(VTK)的過程中衍生品&#xff0c;成為一個獨立的開放源代碼項目。 CMake是一個很強大的編譯配置工具&#xff0c;支持多種平臺和編譯器&#xff0c;通過編寫CMakeLists.txt&#xff0c…

Java 并發---ConcurrentHashMap

concurrent包下的并發容器 JDK5中添加了新的concurrent包&#xff0c;相對同步容器而言&#xff0c;并發容器通過一些機制改進了并發性能。因為同步容器將所有對容器狀態的訪問都串行化了&#xff0c;這樣保證了線程的安全性&#xff0c;所以這種方法的代價就是嚴重降低了并發性…

【圖像處理】——圖像濾波(Python+opencv實現三種方法:均值濾波、中值濾波、高斯濾波等)

目錄 一、什么是濾波以及濾波的目的? 二、均值濾波(cv2.blur()) 1、原理 2、關鍵代碼

UIScrollView事件攔截

在日常的開發中,我們經常會用到UIScrollView,然而,它是一個問題頻出的控件,比如在nib中使用它就必須手動為它創建一個ContentView.當然了使用春代碼的時候使用了懶加載機制使得它能夠擁有一個contentView,今天我們不談這個問題,我們來談談UIScrollView的事件攔截相關的知識. 在…

Windows10下安裝QT5.14.2并用VS2019打開

安裝 從官網下載&#xff1a;QT 安裝方法僅需要注意&#xff1a; 1.最好不要安裝在C盤。 2.根據開發需要安裝功能模塊&#xff0c;具體見參考文章。 https://jingyan.baidu.com/article/656db918d9292ae380249c4f.html 因為是用于PCL編程的&#xff0c;所以只選了msvc2017_64,…

【圖像處理】——圖像質量評價指標信噪比(PSNR)和結構相似性(SSIM)(含原理和Python代碼)

目錄 一、信噪比(PSNR) 1、信噪比的原理與計算公式 2、Python常規代碼實現PSNR計算 3、TensorFlo

Error和Exception的區別

Error&#xff1a;值得是指與虛擬機相關的問題&#xff0c;比如虛擬機崩潰&#xff0c;虛擬機錯誤&#xff0c;內存空間不足&#xff0c;方法調用棧溢出。 對于這類錯誤應建議中斷。 Exception&#xff1a;是指程序員可以處理的異常&#xff0c;可以捕獲并且能夠恢復&#xf…

JAVA TCP/IP網絡通訊編程(二)

一個實例通過client端和server端通訊 客戶端通過TCP/IP傳輸資源文件&#xff0c;比如圖片&#xff0c;文字&#xff0c;音頻&#xff0c;視頻等..... 服務端接受到文件存入本地磁盤&#xff0c;返回接受到&#xff1a;“收到來自于"s.getInetAddress().getHostName()"…

C#中json序列化與反序列化

json格式概念 JSON(JavaScript Object Notation) 是一種輕量級的數據傳輸格式&#xff0c;其采用完全獨立于語言的文本格式&#xff0c;使JSON成為理想的數據交換語言。 json由兩種格式組成。 1.名稱/值”對的集合&#xff0c;可以一起創建多個"名稱 / 值對"。 { “…

volley用法之 以post方式發送 json 參數

需求是這樣 我們需要發送一個post請求向服務器要參數。要求是發送的post參數也要是json格式。 簡單一點的是這樣的&#xff1a; 如果要發送的是這樣簡單的json格式&#xff0c;我們可以簡單的使用map來實現&#xff1a; RequestQueue requestQueue Volley.newRequestQueue(get…

我的友情鏈接

小小忍者Tab轉載于:https://blog.51cto.com/12737170/2043087