将文件中所有数读到一个数组中_「数据结构与算法」将5个文件中的一千万年龄合并到一个新文件中...

现在有5个文件,文件里面分别存储着1千万个用户年龄,并且每个文件中的年龄都是有序的(从小到大),现在需要将这5个文件整合到一个文件中,新文件的内容依然要保持有序(从小到大)。

初始化数据

1.数据生成1千万数据(无序)。

2.将无序的数据进行排序。

3.将排好序的数据写入到文件中。

全局变量类

package com.ymy.file;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;/*** 全局变量*/
public class GlobalVariable {/*** 多线程数量*/public static  int threadNum = 10;/*** 线程池*/public static Executor executor = Executors.newFixedThreadPool(threadNum);/*** 数组总长度*/public static  int arrLenth = 1000;/*** 随机数范围*/public static  int DATA_FIELD = 100;/*** 每个线程的数组长度*/public static  int threadLength = arrLenth/threadNum;/*** 线程同步*/public static CountDownLatch count = new CountDownLatch(10);/*** 线程安全*/public static AtomicInteger atomic = new AtomicInteger(0);public static int arr[] = new int[arrLenth];}

生成随机数方法:

private static Random r = new Random();  /*** 一次性生成1亿数据* @return*/public static int[] getRandomNum1() {int num = GlobalVariable.arrLenth;int arr[] = new int[num];int i = 0;while ( i < num){arr[i] = r.nextInt(GlobalVariable.DATA_FIELD) + 1;i++;}return arr;}

计数排序方法

/*** 计数排序排序** @param ages 需要排序的数组*/public static int[] sort(int[] ages) {
//        long startTime = System.currentTimeMillis();int length = ages.length;if (ages == null || length <= 1) {return ages;}int maxAge = ages[0];for (int i = 1; i < length; ++i) {if (maxAge < ages[i]) {maxAge = ages[i];}}System.out.println("");System.out.println("最大年龄:"+maxAge);int[] countArr = new int[maxAge + 1];for (int i = 0; i <= maxAge; i++) {countArr[i] = 0;}for (int i = 0; i < length; ++i){countArr[ages[i]]++;}
//        for (int i = 0; i <= maxAge; i++) {
//            System.out.print(countArr[i] + " ");
//        }
//        System.out.println("");// 依次累加for (int i = 1; i <= maxAge; ++i) {countArr[i] = countArr[i - 1] + countArr[i];}int[] tmpArr = new int[length];for (int i = length-1 ; i >= 0 ; --i) {int index = countArr[ages[i]]-1;tmpArr[index] = ages[i];countArr[ages[i]]--;}for (int i = 0; i < length; ++i) {ages[i] = tmpArr[i];}
//        long endTime = System.currentTimeMillis();
//        System.out.println("排序已完成,耗时:"+(endTime-startTime)+" ms");return ages;}

文件管理

package com.ymy.file;import java.io.*;
import java.util.ArrayList;
import java.util.List;/*** 文件管理*/
public class FileManager {private static FileReader reader1;private static FileReader reader2;private static FileReader reader3;private static FileReader reader4;private static FileReader reader5;public static  StringBuffer buff= new StringBuffer();public static List<BufferedReader> readList = new ArrayList<BufferedReader>();public static List<FileWriter> writeList = new ArrayList<FileWriter>();public static File file1 = new File("C:UsersAdministratorDesktopdata1.txt");public static File file2 = new File("C:UsersAdministratorDesktopdata2.txt");public static File file3 = new File("C:UsersAdministratorDesktopdata3.txt");public static File file4 = new File("C:UsersAdministratorDesktopdata4.txt");public static File file5 = new File("C:UsersAdministratorDesktopdata5.txt");public static File file = new File("C:UsersAdministratorDesktopfinaldata.txt");private static FileWriter fos1;private static FileWriter fos2;private static FileWriter fos3;private static FileWriter fos4;private static FileWriter fos5;//需要写入的文件public static FileWriter fos;static {try {fos1 = new FileWriter(file1, true);fos2 = new FileWriter(file2, true);fos3 = new FileWriter(file3, true);fos4 = new FileWriter(file4, true);fos5 = new FileWriter(file5, true);fos = new FileWriter(file, true);writeList.add(fos1);writeList.add(fos2);writeList.add(fos3);writeList.add(fos4);writeList.add(fos5);} catch (IOException e) {e.printStackTrace();}try {reader1 = new FileReader(file1);reader2 = new FileReader(file2);reader3 = new FileReader(file3);reader4 = new FileReader(file4);reader5 = new FileReader(file5);} catch (FileNotFoundException e) {e.printStackTrace();}}private static BufferedReader br1;private static BufferedReader br2;private static BufferedReader br3;private static BufferedReader br4;private static BufferedReader br5;static {try {br1 = new BufferedReader(new FileReader(file1));br2 = new BufferedReader(new FileReader(file2));br3 = new BufferedReader(new FileReader(file3));br4 = new BufferedReader(new FileReader(file4));br5 = new BufferedReader(new FileReader(file5));readList.add(br1);readList.add(br2);readList.add(br3);readList.add(br4);readList.add(br5);} catch (Exception e) {e.printStackTrace();}}/*** 读数据* @param reader* @return* @throws IOException*/public static Integer readData(BufferedReader reader) throws IOException {String s = reader.readLine();return null == s ? null : Integer.valueOf(s);}/*** 输入数据到文件** @param arr* @throws IOException*/public static void write(int[] arr, FileWriter fos) throws IOException {System.out.println("写到文件的数据大小:"+arr.length);int length = arr.length;StringBuilder str = new StringBuilder();for (int i = 0; i < length; i++) {str.append(arr[i]);str.append("rn");}writeToFile(str.toString(),fos);}/*** 将数据写入到文件中* @param data*/public static void writeToFile(String data,FileWriter fos){try {fos.write(data);fos.flush();} catch (IOException e) {e.printStackTrace();}}/*** 将数据写入到最终文件夹** @param data* @throws IOException*/public static void dataDispose(int data) throws IOException {buff.append(data);buff.append("rn");
//        fos.write(String.valueOf(data));
//        fos.write("rn");}}

准备内容已差不多,我们现在开始正式将数据分别写入到文件中,请看main函数

/*** 初始化数据* @param args* @throws IOException*/public static void main(String[] args) throws IOException {System.out.println("初始化数据开始");long time = System.currentTimeMillis();for (int i = 0; i<FileManager.writeList.size() ;i++){System.out.println("开始第 "+i+" 文件操作");//初始化数据int[] nums = DataUtil.getRandomNum1();System.out.println("初始化数据完成,数据大小:"+nums.length);//排序int[] sort = AgeSortTest.sort(nums);System.out.println("排序完成,数据大小:"+sort.length);FileManager.write(sort,FileManager.writeList.get(i));System.out.println("写入文件完成");}fos.close();long endTime = System.currentTimeMillis();System.out.println("耗时:"+(endTime - time)/1000 + " s");}

由于我这里没有判断文件是否存在,所以测试的时候你需要先将txt文件建好,否者会报错,运行main函数,我们来看文件数据

1acd9228280d577c976caf4e36410edc.png

看样子文件应该是已经生成成功了,那文件中到底有没有数据呢?请看:

fbefd76ad87d2b4fd3a60bdda7f7a0b2.png

数据刚好是1千万,这是data1文件的数据,其他4个文件中的数据也是类似的,这里就不展示了。

将文件合并写入新文件并保证数据仍然有序

思路:1.分别从5个文件中获取第一条数据。2.比较5条数据的大小,找出最小的一条。3.将最小的数据写入到新文件中。4.在最小一条所在的文件中继续取出一条。5.继续比较5条数据的大小,后面重复上面步骤,直到数据被全部读取完成。

请看main函数

/*** 将文件按顺序写入到新文件中* @param args* @throws IOException*/public static void main(String[] args) throws IOException {long time = System.currentTimeMillis();List<BufferedReader> readList = FileManager.readList;int readListSize = readList.size();int[] arr = new int[readListSize];//读取每个文件第一行,将数据赋值给数组for (int i = 0; i < readListSize; i++) {arr[i] = FileManager.readData(readList.get(i));}int index = DataUtil.comp(arr);FileManager.dataDispose(arr[index]);while(readList.size() > 1){Integer data = FileManager.readData(readList.get(index));if(null == data){readList.remove(index);//从新给数组赋值arr = set(arr,index);}else{arr[index] = data;}index = DataUtil.comp(arr);FileManager.dataDispose(arr[index]);}//最后将for(;;){Integer lastData = FileManager.readData(readList.get(0));if(null == lastData){break;}FileManager.dataDispose(lastData);}FileManager.writeToFile(FileManager.buff.toString(), fos);fos.flush();fos.close();long endTime =  System.currentTimeMillis();System.out.println("操作完成!");System.out.println("操作用时:"+(endTime-time));}

数据对比函数

/*** 数据对比* @param arr* @return*/public static int  comp(int[] arr){//判断数据大小int index = 0;for (int i = 1; i < arr.length; i++) {if(arr[index] > arr[i] ){index = i;}}return index;}

数组重排

/*** 数组重排* @param arr* @param index* @return*/public static int[] set(int arr[], int index){if(arr.length == 1){return arr;}int[]  newArr = new int[arr.length-1];for(int i = 0; i< arr.length-1;i++ ){if(i != index ){newArr[i] = arr[i+1];}else{newArr[i] = arr[i];}}return newArr;}

运行main函数

eacf0f0c49854e534ccb31edc836a42a.png

发现耗时7秒,这速度是块还是慢呢?一个文件一千万数据,5个文件就是5千万,5千万的读取以及5千万的写入耗时7秒,这里的读取是一行一行的读取,但是写入的时候是一次性往新文件中写入5千万数据,那还有没有优化的空间呢?让时间更短一些,其实是有的。1.我们之前做的是一行行的读取,我们可以改为一次读取多行放在内存中,cpu直接往内存中获取数据,获取一条,删除一条,当内存中的数据被删完时,也就代表内存中的数据已经全被使用,这时候就再次往磁盘中读取数据,一次类推,这样也能提升不少性能。2.如果你仔细查看代码你会发现,这里的所有操作都是串行化,第一步:获取到数据才能进行对比;第二步:对比数据;第三步:将最小的数据写入到新文件中;不知道你发现没有,第一步获取数据需要第二部的支持(找到最小的那条数据)才能继续获取数据,但是和第三步并没有任何关系,所以,如果我们能将第一、二步串行;第三步与第一、二步并行,是否能减少运行时间呢?可以考虑Disruptor队列实现。

总结

为什么要使用计数排序

初始化数据的时候我使用了计数排序,我为什么会选择他呢?为什么不选择快排这样的排序方式?

我先介绍一下什么是计数排序:计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)。

由于我们的年龄区间范围并不大,很合适计数排序的要求,所以这里选择计数排序会比快速排序、归并排序等等快很多,如果区间范围太大,计数排序就不适用了,所以使用的时候还是要慎重考虑。

数据初始化是使用多线程是否会比较快?

答案是否定的,你可能会疑惑,多线程不就是来提高性能的吗?使用多线程来初始化数据还是变慢呢?

我们的数据都是一次性生成在内存中,然后再一次性写入到磁盘中,内存中的运行速度是很快的,多线程会牵扯到上下文的切换,这就会让cpu寄存器花更多的时间去保存当前被中断的堆栈,而单线程则不同,因为在内存中,没有线程切换所带来的额外消耗,一个线程会跑的更快,如果我们操作的是磁盘,那么我们就可以考虑使用多线程,因为磁盘的效率很低,会让cpu长期处理空闲时间,所以这时候使用多线程会提高程序的效果,用过redis的都知道,redis就是单线程应用,但是他同样可以达到读:10w/s ;写:8w/s,就是因为redis都是再内存中操作没有上下文的切换,性能会被发挥的很好,这时候你发现内存还是跟不上cpu的速度啊,应该还是有空闲时间,随着技术的发展,我们引入了cpu缓存,也就是cpu需要操作数据的时候会将内存的数据加载到缓存中,后面直接操作缓存即可,cpu往内存拿数据的时候并不是只拿指定的数据,他会获取指定的数据以及它周围的一部分数据,cpu认为它被访问了,那么他周围的数据也有很大可能被访问,这就是有序数组的随机访问比链表的访问速度块的原因之一。

既然是多线程,那么必然会伴随着线程安全问题,我们还要对共享的数据加锁或者进行CAS处理,速度也会受限制,什么时候使用多线程,应该具体问题具体分析,并不是多线程就一定会比单线程速度快。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/507610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二维码编码规范解读

1 QR码符号的结构 QR 码符号的结构如下&#xff1a; 1.1 定位图案 Position Detection Pattern是定位图案&#xff0c;用于标记二维码的矩形大小。这三个定位图案有白边叫Separators for Postion Detection Patterns。之所以三个而不是四个意思就是三个就可以标识一个矩形了…

二维码的纠错码原理及如何纠错(1)

本文将通过例子来说明两个方面的内容&#xff1a; &#xff08;1&#xff09;如何构建纠错码&#xff1f; &#xff08;2&#xff09;有了纠错码之后如何纠错&#xff1f; 1 如何构建纠错码&#xff1f; 直接上例子&#xff0c;“hello world” 利用二维码的编码原理&#xf…

利用自己构建的网络进行鼾声识别

1 目前的工作 1.1 数据 5692条3s且采集率为8000hz的鼾声与6824条3s且采集率为8000hz的其他类音频。通过FFT频谱转换为300个(30,513,1)的矩阵。训练集与测试集的比例为9&#xff1a;1。数据集来源为google开源的数据集。 1.2 模型 图1. The proposed deep neural network arc…

企业微信加密消息体_用企业微信小程序发送消息

在企业开发中&#xff0c;经常会碰到一些消息要及时推送到企业员工的手中。so 下面来说怎么向企业微信中的员工发消息。本人只是记录下开发过程&#xff0c;详细参考https://work.weixin.qq.com/api/1.准备注册企业微信公司获取企业ID新开企业微信应用获取应用的Agentid&#x…

二维码的纠错码原理及如何纠错(2)

下面进一步介绍二维码纠错相关的编码矩阵 1 范德蒙德&#xff08;Vandermonde&#xff09;矩阵 1.1 定义及特性 法国数学家 Alexandre-Thophile Vandermonde 在十八世纪提出了行列式的概念, 用来解决线性方程组问题, 其中一个关键是范德蒙德(Vandermonde) 矩阵, Vandermonde…

NCCIP会议笔记

华南理工大学蔡毅&#xff1a;多智能体通信&#xff0c;识别边界。是否可以用于鼾声识别 天津大学张鹏教授 哈尔滨工业大学 HFUT&#xff1a;俞奎 张长青

计算机创新课,计算机教学课程模式与创新论文

计算机教学课程模式与创新论文摘要&#xff1a;作为大学生通识教育的重要组成部分&#xff0c;计算机基础课程是提高学生信息素养的关键途径。随着互联网技术的不断发展&#xff0c;大学计算机课程教学面临诸多新的挑战&#xff0c;因此需要创新、改革目前的教学模式&#xff0…

New directions in automated traffic analysis论文解读

1 论文主要idea 完整性&#xff1a;没有进行特征提取&#xff0c;保留原始数据包&#xff1b;固定大小&#xff1a;对不同类型的数据包进行统一格式编码&#xff0c;使得编码后的向量大小一致&#xff08;见图3&#xff09;将一些与目标任务不一致的字段去掉&#xff0c;如操作…

计算机找不到wf连接,笔记本wifi功能消失了 电脑wifi连接没了 电脑的wifi不见了...

笔记本wifi功能消失了 电脑wifi连接没了 电脑的wifi不见了2019-11-08 11:14:40 来源&#xff1a;网络扫码可以&#xff1a;1.在手机上浏览2.分享给微信好友或朋友圈解决方法&#xff1a;1、鼠标右键单击电脑桌面右下方的文件夹图标。2、进入文件夹后&#xff0c;在左边列表里&…

计算机二级考试都怎么考,计算机二级都考什么 怎么考

满意答案luluthe...2013.08.26采纳率&#xff1a;45% 等级&#xff1a;11已帮助&#xff1a;8894人关于二级考试科目&#xff1a;与去年相同&#xff0c;二级一共七个科目。二级科目分成两类&#xff0c;一类是语 言程序设计(C、C、Java、Visual Basic、Delphi)&#xff0c;…

计算机c盘丢失,电脑C盘丢失的视频文件怎么恢复?方法讲解,轻松搞定

电脑C盘丢失的视频文件怎么恢复&#xff1f;在日常的工作以及生活当中&#xff0c;有很多的传统媒体文件充斥着。例如&#xff1a;闲暇时&#xff0c;会找一些直播视频来放松自己。工作中&#xff0c;会找一些网络课程来提升自己。但是&#xff0c;在此过程中也会因为一些失误&…

人脸识别研究任务及开源项目调研

0 任务 人脸识别流程包括人脸检测、人脸对齐、人脸识别等子任务。 图1 一些部分遮挡的人脸样本。(a) LFW数据库中部分遮挡的人脸样本。(b)AR数据库部分遮挡的人脸样本。人脸识别具有重要的学术价值&#xff0c;人脸是一类相当复杂的细节变化的自然结构目标&#xff0c;此类目…

双路服务器单路运行,单路还是双路?看需求选择_机箱电源评测-中关村在线

电源的介绍里面&#xff0c;经常会看到“单路12V输出”或者“双路12V输出”的字样。那么单路12V输出和双路12V输出有什么区别呢&#xff1f;单路12V输出有着什么样的优势&#xff0c;而双路12V又有着什么样的优势呢&#xff1f;接下来简单分析一下。单路输出电源的12V输出主要是…

计算机常用控温算法,常用温度控制方法原理 -解决方案-华强电子网

常用PID调节器/温控仪控制算法包括常规PID、模糊控制、神经网络、Fuzzy-PID、神经网络PID、模糊神经网络、遗传PID及广义预测等算法。常规PID控制易于建立线性温度控制系统被控对象模型&#xff1b;模糊控制基于规则库&#xff0c;并以绝对或增量形式给出控制决策&#xff1b;神…

我的世界服务器修改数据,我的世界常用指令大全,轻松调整服务器数值状态

在我的世界服务器中能够经过输送指令来微调服务器的一些数值状态&#xff0c;此次就为各位提供我的世界常用指令大全&#xff0c;毕竟我的世界作为一款出色的沙盒游戏&#xff0c;不止是因为原版内容和mod的增光填色&#xff0c;也离不开指令的辅助。/say [语句]让服务器发每段…

二维码的目标定位

1 总体思路 第一步&#xff0c;寻找二维码的三个角的定位角点&#xff0c;需要对图片进行平滑滤波&#xff0c;二值化&#xff0c;寻找轮廓&#xff0c;筛选轮廓中有两个子轮廓的特征&#xff0c;从筛选后的轮廓中找到面积最接近的3个即是二维码的定位角点。 第二步&#xff1…

mac 上传ftp服务器文件夹权限,mac 访问 ftp服务器文件夹权限

mac 访问 ftp服务器文件夹权限 内容精选换一换在“云服务器列表”页&#xff0c;单击下拉按钮展开会话列表&#xff0c;查看会话连接状态&#xff0c;出现“关闭应用失败”的异常。将鼠标移动至“关闭应用失败”处&#xff0c;查看具体的失败原因&#xff0c;并根据表1进行故障…

以毒攻毒Fight Fire with Fire: Towards Robust Recommender Systems via Adversarial Poisoning Training论文解读

1 摘要 最近的研究表明&#xff0c;推荐系统是脆弱的&#xff0c;攻击者很容易将精心设计的恶意配置文件注入系统&#xff0c;从而导致有偏见的推荐。我们不能否认这些数据的合理性&#xff0c;因此建立一个强大的推荐系统势在必行。对抗性训练已被广泛研究以获得可靠的建议。…

redis延迟队列 实现_灵感来袭,基于Redis的分布式延迟队列

一、延迟队列延迟队列&#xff0c;也就是一定时间之后将消息体放入队列&#xff0c;然后消费者才能正常消费。比如1分钟之后发送短信&#xff0c;发送邮件&#xff0c;检测数据状态等。二、Redisson Delayed Queue如果你项目中使用了redisson&#xff0c;那么恭喜你&#xff0c…

opencv2 取二进制数据_百亿数据量下,掌握这些Redis技巧你就能Hold全场

程序猿DD一、Redis封装架构讲解实际上NewLife.Redis是一个完整的Redis协议功能的实现&#xff0c;但是Redis的核心功能并没有在这里面&#xff0c;而是在NewLife.Core里面。这里可以打开看一下&#xff0c;NewLife.Core里面有一个NewLife.Caching的命名空间&#xff0c;里面有一…