插入1000w條記錄到文本文件並讀取做分組排序

背景

某司線上筆試題

隨機生成 Salary {name, baseSalary, bonus }的記錄,如“wxxx,10,1”,每行一條記錄,總共1000萬記錄,寫入文本文件(UFT-8編碼),然後讀取文件,name的前兩個字符相同的,其年薪累加,比如wx,100萬,3個人,最後做排序和分組,輸出年薪總額最高的10組,並將其儘量優化到五秒

package subject.demo.two;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * @author cmai/nico
 * @createDate 2018/11/12
 * @description
 */
public class Application {

    static int append = 0;

    public static void main(String[] args) throws IOException, InterruptedException {
        //文件
        File file = new File("D:/demo2.txt");
        if (file.exists()) {
            file.delete();
            file.createNewFile();
        }
        FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
        BufferedWriter bw = new BufferedWriter(fw);

        long startTime = System.currentTimeMillis();

        //記錄條數
        final int count = 10000000;
        final int batch = 1000;
        final int lop = count/batch;
        final CountDownLatch countDown = new CountDownLatch(lop);

        ThreadPoolExecutor service = new ThreadPoolExecutor(1000, 1000, 0, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        for(int start = 0; start < lop; start ++) {
            service.execute(() -> {
                StringBuffer stringBuffer = new StringBuffer();
                for (int i=0; i < batch; i++){
                    stringBuffer.append(getRandomString(4) + "," +(int) (Math.random() * 9000 + 1000) + "," +(int) (Math.random() * 9000 + 1000));
                    stringBuffer.append("\r\n");
                }
                try {
                    synchronized (bw) {
                        bw.write(stringBuffer.toString());
                        bw.flush();
                        countDown.countDown();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
        countDown.await();
        bw.close();
        System.out.println("insert finish");

        FileReader reader = new FileReader(file);
        BufferedReader br = new BufferedReader(reader);
        String line = null;
        int c = 0;

        Map<String, Integer> map = new HashMap<>();
        Map<String,Long> countMap = new HashMap<>();

        int lineCount = 0;
        while((line = br.readLine()) != null) {
            final String[] infos = line.split("[,]");
            String start = infos[0].substring(0, 2);
            int yearSalary = Integer.parseInt(infos[1]) + Integer.parseInt(infos[2]);
            Integer s = map.get(start);
            if(s != null) {
                map.put(start, yearSalary + s);
                countMap.put(start,countMap.get(start)+1);
            }else {
                map.put(start, yearSalary);
                countMap.put(start,1L);
            }
            ++lineCount;
        }
        List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
        Collections.sort(list, (o1, o2) -> o1.getValue().compareTo(o2.getValue()));
        for (int i =0;i<10;i++){
            String key = list.get(i).getKey();
            System.out.println(key+","+list.get(i).getValue()+"萬,"+countMap.get(key)+"人");
        }
        System.out.println("line:" + lineCount);
        System.out.println("耗時:" + (System.currentTimeMillis() - startTime) + " ms");
        service.shutdown();
    }

    public static String getRandomString(int length){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(5);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }
}


其實還是有點問題,當時比較倉促,其實分組和排序可以在插入的時候做,不用再讀取一遍。
筆試通過了,去現場面試做了套筆試題滾蛋了 233…
感謝大表哥提供forkjoin的思路

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章