文章目录
话接前回, https://editor.csdn.net/md/?articleId=125025105网上大部分文章都照抄照搬,但是这个文章里的代码还是有问题的。
有一个10G文件的数据,里面包含了18-70之间的整数,分别表示18-70岁的人群数量统计,假设年龄范围分布均匀,分别表示系统中所有用户的年龄数,找出重复次数最多的那个数。
最终我也重新写了个代码,处理起来应该是对的了,代码并没有在他的基础上进行改变,而是重新写了,至于创建10G文件的话,用的还是原来的,接下来就记录一下怎么处理的?
我写的示例结构如下:
1.创建文件,大小为10G左右
创建文件的格式为:数据全都在17-70之间,包括17和70,每一百万个数据为一行,数据之间用","分隔开,最后行末有一个换行符,100万条数据大概4M,10G的文件总共有2500行左右。
创建代码如下:
/**
* 创建10G的文件
*/
public class GenerateData {
private static Random random = new Random();
public static int generateRandomData(int start, int end) {
return random.nextInt(end - start + 1) + start;
}
/**
* 产生10G的 1-1000的数据在F盘
*/
public void generateData() throws IOException {
File file = new File("F:\\ User.dat");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
int start = 18;
int end = 70;
long startTime = System.currentTimeMillis();
BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
for (long i = 1; i < Integer.MAX_VALUE * 1.7; i++) {
String data = generateRandomData(start, end) + ",";
bos.write(data);
// 每100万条记录成一行,100万条数据大概4M
if (i % 1000000 == 0) {
bos.write("\n");
}
}
System.out.println("写入完成! 共花费时间:" + (System.currentTimeMillis() - startTime) / 1000 + " s");
bos.close();
}
public static void main(String[] args) {
GenerateData generateData = new GenerateData();
try {
generateData.generateData();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这个代码是独立的,只是用于创建10G的文件,与下边的代码无关。
差不多花了4min
2.问题分析
在一个10G文件的数据,里面包含了18-70之间的整数,找出重复次数最多的那个数。
第一步:应该找出每一行中的出现的数,以及这个数出现的次数,之后进行形成一个映射,也就是一个Map,这样可以节约内存空间。
比如:20这个数在第一行中出现了5次,那么就形成一个HashMap结构。key=20,value=5,
Map<Integer, Integer> mapSum = new HashMap<Integer, Integer>();
第二步:用多线程进行读取,开启多个线程对文件进行每行读取,当读到完整一行时就将其中的数据以及出现的次数用Map结构存储并返回。
注意:每个线程都需要返回一个Map,所以需要实现Callable接口。
第三步:将每个线程返回的Map进行接受,并对Map进行汇总,统计出所有Map中的数据集。
代码如下:
(1)主线程(MultiThreadReadByLine 类)
public class MultiThreadReadByLine {
public static void main(String[] args) {
FileReader fileReader = new FileReader("F:\\ data.dat", 1024000, 20);
fileReader.registerHanlder(new FileLineDataHandler());
//统计所有map
Map<Integer, Integer> mapSum = new HashMap