将文件中所有数读到一个数组中_「数据结构与算法」将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,一经查实,立即删除!

相关文章

成都理工大学工程技术学院计算机专业收分线,2019年成都理工大学工程技术学院美术类专业录取分数线...

四川&#xff1a;艺术本科省控线文化分370专业分200(单科成绩均不低于60分)&#xff0c;录取最低专业分224&#xff1b;艺专省控线文化分140专业分160&#xff0c;录取最低专业分181。内蒙古&#xff1a;艺术本科省控线文化分279专业分199&#xff0c;录取最低专业分201&#x…

如何利用python语言实现对象数组

1 Java代码示例 //定义一个类 class Triple {int user;int item;double rating; &#xff5d;//声明对象数组 Triple[] dataset new Triple[20];//利用对象数组访问成员变量 for(int i 0; i < dataset.length; i ){dataset[i].user 0; dataset[i].item 0dataset[i].…

在python中、正确的函数定义格式为_Python函数的定义与实现

1. 函数的介绍函数是 实现具有特定功能的代码块Python中预制了许多内置函数&#xff0c;也可以根据自己的需求创建自定义的函数隐藏实现功能的细节代码的复用提高可读性&#xff0c;便与调试def 函数名(形参1, 形参2...):要运行的代码块(函数体)return 返回的数据(返回值)函数名…

计算机连接交换机配置命令,[计算机]交换机配置命令.doc

[计算机]交换机配置命令交换机配置命令集锦1、 进入全局配置模式1、Switch-3548 > enablePassword : ********Switch-3548 # config tSwitch-3548 (config) #2、 启用交换机的HTTP Server2、Switch-3548 (config) # ip http server3、 配置主机名3、Switch-3548 (config) # …

二维码编码规范解读

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

最早单机的计算机操作系统,川农《计算机操作系统(本科)》19年12月在线作业【满分答案】...

可做奥鹏全部院校作业论文&#xff01;答案请添加qq&#xff1a;599792222 或 微信&#xff1a;1095258436川农《计算机操作系统(本科)》19年12月在线作业【满分答案】试卷总分:100 得分:100一、单选题 (共 20 道试题,共 100 分)1.在单一处理机上执行程序&#xff0c;多道程序…

pythonopencv提取圆内图像_python – 使用OpenCV从图像中提取多边形给定...

使用cv2.fillConvexPoly以便您可以指定2D点阵列并定义一个蒙版,该蒙版填充由这些点定义的形状在蒙版中为白色.如果多边形中定义的点是凸的(因此名称为fillConvexPoly),则应该进行一些公平的警告.然后我们可以将其转换为布尔蒙版,并使用它来索引图像以提取出您想要的像素.下面的…

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

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

浙江省二级计算机vfp,浙江省计算机2级vfp程序调试真题集.doc

程序填空(改错)题&#xff1a;在考生文件夹的paper 子文件夹中&#xff0c;已有文件Modify.prg&#xff0c;请自己打开文件&#xff0c;在标记&&之前填写所缺代码、调试、保存&#xff0c;并完成以下功能1、显示指定表中的全部字段名&#xff0c;并由用户输入显示表信息…

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

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…

计算机组成码距,计算机组成原理:2.3.2 纠错码原理.ppt

2.3.2 纠错码的基本原理;重复码;;n4时;译码失败&#xff1a;译码器根据接收到的信号无法作出明确判断;纠错码如何纠正错误&#xff1f;;2.3.3 几个基本概念;许用码组和禁用码组;错误图样;汉明距离和重量;最小码距;分组码 分组码一般可用(n,k)表示。其中&#xff0c;k是每组二进…

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

在企业开发中&#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…

北师大计算机组成原理离线作业,北师大网络教育 离线作业 计算机组成原理(一、二、三)...

《计算机组成原理》作业(一)一、CPU&#xff1a;Central Processing Unit 中央处理单元 执行存放在主存储器中的程序即机器指令.CPU是由控制器和运算器.PC&#xff1a;Personal Computer 个人电脑 能独立运行、完成特定功能的个人计算机 IR&#xff1a;Immediate Rendering 直接…

3dsmax导出html,3dsmax导出gltf格式插件

【实例简介】3dsmax导出gltf格式插件&#xff0c;里面包括插件&#xff0c;插件使用说明&#xff0c;插件功能介绍&#xff1b;【实例截图】【核心代码】3dsmx_to_gltf格式插件└── 3dsMax to gltf 2├── 3ds Max│ ├── CHANGELOG.md│ ├── Max2Babylon│ │ …

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;如操作…

拉力测试软件界面,电脑拉力机/电脑控制拉力试验机软件操作界面与功能

1、电脑控制软件能实现自动读取抗拉强度、屈服强度、断裂强度、弹性模量、延伸率等检测数据&#xff0c;公式编辑能自动计算试验过程中任一指定点的力、应力、位移、变形等数据结果。对试验过程的控制和数据处理符合相应金属材料与非金属材料国家标准的要求。2、 控制方式&…

NSA-LDL论文修改建议20211026BRT

repair --> 增强&#xff0c;丰富&#xff0c; The kkk-nearest neighbor algorithm enhances the feature representation of the target sample by obtaining neighbors. Most of them take account of label correlation which plays an importance role in LDL. –>…