论坛首页 Java企业应用论坛

这不是面试题,这是真事

浏览 38743 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-07-26  
Trie树(字典树),如果用Trie树来存你“第二行的整数”应该不要多少内存。
0 请登录后投票
   发表时间:2013-07-26  
1.对文件每次读100,000行.对其中第二列的数据读出来进行根据10取模其实就是根据尾数分成10个文件存,存的时候可以开10个线程。读完两亿行数据。如果数据分布是比较平均的基本上每个文件会有大概两千行的数据。但是这个容量会比较小因为每条记录是15bytes * 2000 * 10000 = 300M
2.同时10线程分别对各个300M的数据进行读取处理。
0 请登录后投票
   发表时间:2013-07-26  
两千万行 上面错了
0 请登录后投票
   发表时间:2013-07-26  
先扫描一次文件,用一个hash表计数第二个字段,将计数>1的值输出。
然后将这些值存储在一个set中,然后再扫描一次文件,第二个字段在set中的输出行。。

原则:

文件很大,不能用排序。
2亿行的文件,我的经验用不了多长时间,半个小时顶天了。
如果你的文件在hadoop平台的话,写个sql,真的是分分钟的事情。

0 请登录后投票
   发表时间:2013-07-26  
awk -F "\t" '{print $2| "sort -n | uniq -d" }' FILE
0 请登录后投票
   发表时间:2013-07-27   最后修改:2013-07-27
果断shell

awk '{++num[$2]} END{ for(n in num){ if(num[n]>=2) print n,num[n] } }' file

看错题目,找出行的话应该是下面的脚本

awk '{++num[$2];if(num[$2]>=2){print $0}}' file
0 请登录后投票
   发表时间:2013-07-27  
bruce.yuan 写道
果断shell

awk '{++num[$2]} END{ for(n in num){ if(num[n]>=2) print n,num[n] } }' file

看错题目,找出行的话应该是下面的脚本

awk '{++num[$2];if(num[$2]>=2){print $0}}' file



嗯,这个是正确的做法。pass through 解决
0 请登录后投票
   发表时间:2013-07-28  
iceman1952 写道
我有一个文件,一共100列,每个列以 tab 分开,第二列是一个 15位 的整数(此列是乱序的)
文件行数在2亿行之内,文件很大,大约 50G 左右。现在要求我找出 满足这种条件的行:第二列的整数,在此文件中,出现过2次或2次以上

有啥好办法嘛?
我现在这么搞的:将文件尽量分成小文件(保证同样的数字分到同一个小文件中),使得此文件可以整个load到内存中。然后对内存中的数据使用set看是否曾经重复出现过
根据最后一位的值(0, 1, ..., 9),分成10个child文件。如果某个child文件还大于512M(我JVM内存比512大一点点,可以load整个文件),在根据第二位再分割此child文件,得到 grandchild文件;如果grandchild文件还是大于512M,则根据第三位分割......


缺点:太耗时,以至于不现实,要1个多小时

PS:我将 JVM 最大heap设为 1024M,然后,测试将Long加入到set中,发现,可以创建 1700W个Long对象(Integer对象也是这么多)。到production环境中,我估计heap可以设置到8G,但是,即使这样,也只有1.6亿的Long(或者Integer),所以,肯定还是不能够读入所有的 整数,然后使用set判断哪个曾经出现过2次或2次以上

各位,有好办法嘛?我只要知道哪些整数曾经出现过2次或2次以上即可(分不分文件、出现的确切次数 我都不在乎)

另外:不要建议分布式啥的,这个也用不起来,我这就是一个 standalone 的应用



这事儿没那么麻烦吧。第二列是15位的整数,一共2亿个,使用long型数组(或HashSet),大概占用1.6G内存,不要用Long型对象。如果第二列的整数有重复,还会节约些内存。

然后全局遍历50G的这个大文件,在这个数组(或者HashSet)里面去找就可以了。其实50G的文件还不算太大。

生产环境如果能提供8G内存,这个做起来没问题的,你用512M内存是不是太小气了些?

其实还有个最傻X的办法:花上几千块钱,买64G或128G内存,把这个50G的文件扔进内存,然后……你懂的

如果确实蛋疼没事儿干,还可以考虑多线程处理,速度肯定会更快的。
0 请登录后投票
   发表时间:2013-07-28   最后修改:2013-07-28
awk -F'\t' '{if(a[$2]++ >=2){print $2}}' test.txt >newfile.txt

50G大小预计30分钟
0 请登录后投票
   发表时间:2013-07-29  
研究了一下大概描述下思路:
(1)位图:这个可能需要把用15位的数字作为下标,已经超过数组下标为整型的限制,就算没有这个限制(或找到其他实现方式),15整数的作为下标的数组,占用内存达到999999999999999l/(1024*1024*1024)=931322.5746154776(单位g),这个太吓人了,前提还是java中有真正位图的实现,否则如果最小单位不是bit,是byte的话内存还要增加;
(2)long[] lArr =  new long[120000000];测试了一下最大heap设置1g时能存储大概120000000个基本类型long,如果到2g的内存应该就能存储超过2亿个long,剩余内存用来计算;包装类型使用的内存要大于基本类型,这和楼主的测试(可以创建 1700W个Long对象)差不多,这种情况是不是采用基本类型合理一点,注:不知道楼主的环境能否跨越java虚拟机内存限制(一般是达不到2g的),哪位能否告诉一下怎么突破这个限制;
(3)方法2不行就只能拆分文件了,是不是要找到算法让数据尽可能均匀分布到子文件中呢?(对这个比较感兴趣,希望有经验的兄弟分享下拆分的策略)
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics