簡體   English   中英

用Java排序大文件

[英]Sort huge file in java

我的文件很大,每一行都有唯一的單詞。 文件大小約為1.6 GB(此后我必須對其他文件進行排序,約為15 GB)。 到目前為止,對於較小的文件,我使用Array.sort() 但是對於這個文件,我得到了java.lang.OutOfMemoryError: Java heap space 我知道此錯誤的原因。 有什么辦法可以代替編寫完整的快速排序或合並排序程序。

我讀到Array.sort()在內部使用Quicksort或Hybrid Sort。 有沒有像Array.sort()這樣的程序?

如果必須編寫用於排序的程序,應該使用哪個程序? 快速排序或合並排序。 我擔心最壞的情況。

根據要存儲的數據的結構,您可以執行許多不同的操作。

如果數據結構良好,則需要按一個或多個特定字段進行排序(在這種情況下,系統工具可能無濟於事),最好使用允許排序的數據存儲。 考慮到大小不超過100 GB,MongoDB非常適合此操作。 其他的NoSQL數據存儲區也可能很合適,盡管Mongo使用和安裝的簡單性以及對JSON數據的支持使其成為了一個不錯的選擇。

如果您真的想使用Java方法,那么它將變得非常棘手。 這是您在工作面試中提出的問題,我從不希望任何人實現代碼。 但是,一般的解決方案是合並排序(使用隨機訪問文件是一個壞主意,因為這意味着插入排序,即非最佳運行時間,考慮到文件的大小,這可能很糟糕)。

通過合並排序,我的意思是一次讀取文件的一個大塊,使其足夠小以適合內存(因此,這取決於您擁有多少RAM),對其進行排序,然后將其寫回到磁盤上的新文件中。 讀取整個文件后,您可以通過一次讀取每個文件的開頭並將(兩個記錄中較小的一個)寫回第三個文件來開始合並兩個塊文件。 對“第一代”文件執行此操作,然后繼續第二個文件,直到最終得到一個大排序文件。 請注意,這基本上是實現合並排序的自下而上的方法,學術遞歸算法是自上而下的方法。

請注意,通過使用多路合並算法可以完全避免具有中間文件。 這通常基於堆/優先級隊列,因此實現可能會稍微復雜一些,但會減少所需的I / O操作數量。

另請參閱這些 鏈接

盡管經過一定的精心設計,但在Java中實現上述目標應該不會太困難。 我仍然強烈推薦像Mongo這樣的現成解決方案。

事實證明,您的問題是您的堆無法容納如此大的數組,因此您必須忘記任何暗示將整個文件內容加載到數組中的解決方案(只要您不能擴大堆)。

因此,您正在面對流媒體。 當您必須處理大於可用內存的輸入源時,這是唯一(典型)的解決方案。 我建議將文件內容流式傳輸到您的程序,該程序應通過輸出到隨機訪問文件(trickier)或數據庫來執行排序。

我會采取另一種方法。

給定一個文件(例如每行只有一個元素),我將讀取前n元素。 我將重復m次,以使文件中的行數為n * m + C其中C為剩余行。

在處理Integers ,您可能希望每次讀取使用大約100,000個元素,而使用Strings我會使用較少的元素,也許大約是1,000個。 它取決於每個元素所需的數據類型和內存。

從那里,我將對n個元素進行排序,並將它們寫入具有唯一名稱的臨時文件中。

現在,由於所有文件都已排序,因此最小的元素將在開始。 然后,您可以遍歷文件,直到處理完所有元素為止,找到最小的元素並將其打印到新的最終輸出中。

這種方法將減少所需的RAM數量,而是依賴驅動器空間,並使您可以處理任何文件大小的排序。

在文件(索引類型)中建立記錄位置的數組,也許它可以放入內存中。 每個文件記錄需要8字節long Java。 對數組進行排序,僅加載記錄以進行比較,而不保留(使用RandomAccessFile )。 排序后,使用索引指針寫入新的最終文件以按所需順序獲取記錄。

如果記錄的大小不同,這也將起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM