首页 > 其他分享 >面试:大文件拆分排除输出

面试:大文件拆分排除输出

时间:2024-08-26 13:56:31浏览次数:12  
标签:文件 String 输出 File filePath 面试 拆分 new 排序

题目:

        存在这样一个场景:在内存紧够存储1GB数据的情况下,如何把一个10G文件进行排序后输出,10G的文件每行数据为Long型的正整数,请代码实现;

题目分析

        题目核心在于以下两点:

1、内存仅能够存储1GB,即不能把所有数据在内存中排序后再输出;

2、源文件是无需的,需要先进行排序;

3、输出后仍未一个文件;

实现思想

        通过上述简单分析,可以看出,需要通过分治的方式,分批读取文件,可以按照1GB文件读取,读取之后排序,然后输出到part文件,然后再遍历排序后的10个文件,按照堆排序思想,取第一个元素,即10个文件第一个元素,哪个最小,哪个先输出,然后最小的哪个值来自哪个文件,这个文件再进行遍历,当所有的文件均遍历完成后,再排序输出完成,

实现代码


import java.io.*;
import java.util.*;

public class FileSort {

    public static final String ROOT_PATH = "D:/temp/test";

    public static final String SAMPLE_ORI_BIG_FILE = "ori.txt";
    public static final String SAMPLE_RESULT_BIG_FILE = "result.txt";

    /**
     * 模拟生成一个大文件,包含Long型的整数数据
     */
    public static void testData() throws IOException {
        String filePath = ROOT_PATH + File.separator + SAMPLE_ORI_BIG_FILE;
        Random random = new Random();
        if(!new File(filePath).exists()){
            new File(filePath).createNewFile();
            int count = 1000000;
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(filePath)))) {
                while (count-- > 0) {
                    long l = Math.abs(random.nextLong());
                    writer.write(String.valueOf(l));
                    writer.newLine();
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        //0、生成模拟数据
        testData();
        //1、读取源文件,按照固定大小排序并输出文件
        String filePath = ROOT_PATH + File.separator + SAMPLE_ORI_BIG_FILE;
        splitFileAndSorts(filePath,100000);
        //2、10个文件遍历读取,放到堆中,取最小的数据出到文件中,输出的元素,读取下一条,然后再比较,以此往复
        List<BufferedReader> readerList = new ArrayList<>(10);
        for(int i = 1;i<=10;i++){
            String partFilePath = filePath + ".part" + i;
            BufferedReader reader = new BufferedReader(new FileReader(new File(partFilePath)));
            readerList.add(reader);
        }
        String resultFilePath = ROOT_PATH + File.separator + SAMPLE_RESULT_BIG_FILE;
        BufferedWriter writer = new BufferedWriter(new FileWriter(new File(resultFilePath)));

        Boolean flag = Boolean.FALSE;
        Set<Integer> skipIndex = new HashSet<>();
        Map<Integer,Long> indexLongMap = new HashMap<Integer,Long>();
        int index = 0;
        while (!flag){
            for(int i = 0;i<readerList.size();i++){
                if(!skipIndex.contains(i)) {
                    if(null == indexLongMap.get(i)) {
                        BufferedReader reader = readerList.get(i);
                        String str = reader.readLine();
                        if (str != null) {
                            Long s = Long.parseLong(str);
                            indexLongMap.put(i, s);
                        } else {
                            skipIndex.add(i);
                        }
                    }
                }
            }
            if(skipIndex.size() == 10){
                flag = Boolean.TRUE;
            }else {
                Long min = 0L;
                for (Integer i : indexLongMap.keySet()) {
                    Long s = indexLongMap.get(i);
                    if (min <= s) {
                        min = s;
                        index = i;
                    }
                }
                writer.write(String.valueOf(min));
                writer.newLine();
                indexLongMap.remove(index);
            }
        }
        writer.flush();
    }

    /**
     *
     * @param sourceFilePath
     * @param nums
     */
    public static void splitFileAndSorts(String sourceFilePath, int nums) throws IOException {
        List<Long> sortedList = new ArrayList<>(nums);
        int i = 1;
        String s = null;
        try (BufferedReader reader = new BufferedReader(new FileReader(new File(sourceFilePath)))) {
            while ((s = reader.readLine()) != null) {
                sortedList.add(Long.parseLong(s));
                if (sortedList.size() >= nums) {
                    Collections.sort(sortedList);
                    String partFilePath = sourceFilePath + ".part" + i;
                    try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(partFilePath)))) {
                        for (Long l : sortedList) {
                            writer.write(String.valueOf(l));
                            writer.newLine();
                        }
                    }
                    sortedList = new ArrayList<>(nums);
                    i++;
                }
            }
        }
    }

}

结果展示

排序后的文件内容

标签:文件,String,输出,File,filePath,面试,拆分,new,排序
From: https://blog.csdn.net/qq_43462685/article/details/141562185

相关文章

  • 光性能 -- 标称单波输入/输出光功率&标称增益
    光功率计算        光功率表示光信号能量的强弱,是波分系统的关键参数之一。光功率过大可能烧坏光器件,光功率过小,接收机就接收不到光信号。        功率的国际单位是W(瓦特)。波分系统中传输的都是弱信号,功率值都非常小,所以用mW(毫瓦)表示。由于直接使用mW计......
  • 别着急面试㊙先背完答案✅offer接到手软
    别着急面试㊙先背完答案✅offer接到手软21/100保存草稿发布文章2401_85378759未选择任何文件new面试大模型岗的小伙伴们最近面试题背的怎么样啦-大模型(LLM)面试题是面试中比较常问到的,今天给大家整理了120个常见的大模型面试题✅1、目前主流的开源模型体系有哪些?(高......
  • 示波器输出的csv文件如何转换为频谱图及其excel表格(频率与幅值)
    示波器输出的CSV文件通常包含的是采样的时域信号数据,而不是直接的频率和幅度信息。这个文件一般包括时间(Time)和电压(Voltage)两列,记录了电压随时间变化的情况。要从这些时域数据中得到频率和幅度的变化,你需要进行一些信号处理,通常步骤如下:①导入CSV数据:读取CSV文件中的时间和电......
  • 计算机网络面试真题总结(四)
    文章收录在网站:http://hardyfish.top/文章收录在网站:http://hardyfish.top/文章收录在网站:http://hardyfish.top/文章收录在网站:http://hardyfish.top/什么是滑动窗口TCP滑动窗口是TCP协议中实现流量控制和可靠传输的关键机制。滑动窗口不仅可以防止发送端数据传输......
  • 线程池相关面试题
    一、JDK自带的线程池有那些?1.Executors.newCachedThreadPool()创建一个可缓存线程的线程池,若线程池长度超出需要,可回收线程,若没有可回收,则新建线程2.Executors.newFixedThreadPool()创建定长线程池,可控制线程最大并发数,超出的线程在队列中等待3.Executors.newScheduled......
  • 京东面试:600Wqps高并发ID如何设计?时钟回拨 如何解决?
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • 大模型-qwen-turbo(流式输出)
    #流式输出fromdjango.httpimportStreamingHttpResponsefromdashscopeimportGenerationfromrest_framework.decoratorsimportaction#定义一个生成服务器发送事件(SSE)的函数defgenerate_sse(responses):#遍历每个响应forresponseinresponses:......
  • 【面试系列】30个常见的初级SQL编程题
    欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏:工......
  • 【面试系列】大数据平台常见面试题解答
    欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏:工......
  • Java笔试面试题之多线程常见考点总结
    Java多线程面试题涵盖了Java多线程编程的多个重要方面,主要考察面试者对Java并发编程的理解和应用能力。以下是常见的考点总结:基本概念与区别:进程与线程的区别:进程是资源分配的基本单位,线程是CPU调度的基本单位,线程共享进程资源。Java堆与栈的区别:堆用于存储对象实例,栈用......