作者:清雅竹gf_644 | 来源:互联网 | 2023-10-11 14:02
一、需求
有1个大文件包含5亿个数(文件大小好几个G),其中每一行都是一个随机整数(不重复),现在要对这个文件进行排序。
二、实现
2.1 位图法
核心思想是,创建一个拥有5亿bits的BitSet(位图),BitSet每一位初始时都为false。然后读取包含正整数的文件,对于每一个数i,将bitSet[i]设置为true。最后遍历位图,如果bitSet[j]为true,那么输出 j。
采用位图法,也可以判断某个给定的数是否在大文件中,只需要判断bitSet的指定位是否为true即可。
下面是我写的一个简单的demo,用于对文件中的数字排序:
data.txt内容如下:
代码如下:
public static void main(String[] args) {BitSet bitSet = new BitSet(100);try (BufferedReader br = new BufferedReader(new FileReader("F:\\data.txt"))) {String line = null;while ((line = br.readLine()) != null) {int value = Integer.valueOf(line);bitSet.set(value);}} catch (Exception e) {e.printStackTrace();}for (int i = 0; i 结果如下:
1
7
9
12
32
43
87
765
32543
2.2 外部排序
在内存极小的情况下,采用分治策略,利用外存保存中间结果,再用多路归并来排序。
map-reduce思想:
内存中维护一个极小的缓冲区buffer,将大文件bigdata按行读入,直到buffer满或者大文件读完时,对buffer中的数据调用内排进行排序,排序后将有序结果写入磁盘临时文件bigdata.xxx.part.sorted,循环利用buffer直到大文件处理完毕,得到n个有序的临时文件。
接下来,对n个有序的临时文件进行归并排序,方法如下:假如有三个临时文件,其中文件1:3,6,9,文件2:2,4,8,文件3:1,5,7。
第一回合:文件1的最小值:3 , 排在文件1的第1行,文件2的最小值:2,排在文件2的第1行,文件3的最小值:1,排在文件3的第1行 那么,这3个文件中的最小值是:min(1,2,3) =1。也就是说,最终大文件的当前最小值,是文件1、2、3的当前最小值的最小值。上面拿出了最小值1,写入大文件。
第二回合:文件1的最小值:3,排在文件1的第1行,文件2的最小值:2,排在文件2的第1行,文件3的最小值:5,排在文件3的第2行。那么,这3个文件中的最小值是:min(5,2,3) = 2,将2写入大文件。
接下来,重复上述操作,直到所有小文件的内容都写到了大文件。
参考:
https://blog.csdn.net/zxx901221/article/details/83028481
https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&mid=2247488950&idx=2&sn=a3f4a09acd07638055c803338c15e29e&chksm=fa496a07cd3ee3117a27f17818ddc4152a817b50961780ae65ce3ac545303092221b08778e16&mpshare=1&scene=1&srcid=&sharer_sharetime=1582344585643&sharer_shareid=cfcd208495d565ef66e7dff9f98764da&key=56dae8b8a643d0f33cf6fdae6748f10f94d93459951fc0f564b244e54c6e8de6cce77ff794210f989a83231ae733a61f773233f7a4f5cbe90fac0ba3b3f194898dacea95b4b6667befc1c49ea94fd347&ascene=1&uin=MjI5NzkwNjI0Mg%3D%3D&devicetype=Windows+10&version=62070158&lang=zh_CN&exportkey=A9Ay4nz6HZO2bU0iugefePI%3D&pass_ticket=FW9GJdVHO2LjxiXcRXeofaBYJdcXuPY6k3di%2BzwOyVBLknE63w20ogQQfIUitcCY