JAVA8快速寫入和讀取文件

JAVA8快速寫入和讀取文件?

話很少說,先看題:java

隨機生成 Salary {name, baseSalary, bonus }的記錄,如「wxxx,10,1」,每行一條記錄,總共1000萬記錄,寫入文本文件(UFT-8編碼), 而後讀取文件,name的前兩個字符相同的,其年薪累加,好比wx,100萬,3我的,最後作排序和分組,輸出年薪總額最高的10組:app

​ wx, 200萬,10人dom

​ lt, 180萬,8人ide

​ ....函數

name 4位a-z隨機,baseSalary [0,100]隨機 bonus[0-5]隨機 ,年薪總額 = baseSalary*13 + bonus。性能

思路:優化

第一步:先編寫一個Salary對象

裏面包含有name,baseSalary, bounus屬性,而後編寫一個構造器,重寫toString()方法方便序列化數據,同時編寫構建Salary對象的方法build();ui

/**
 *  name 4位a-z隨機
 *  baseSalary 0-100隨機
 *  bonus 0-5隨機
 *  年薪總額 = baseSalary * 13 + bonus
 */
class Salary {
    // name 4位a-z隨機,baseSalary 0-100隨機,bonus 0-5隨機 年薪總額 = baseSalary * 13 + bonus
    private String name;
    private int baseSalary;
    private int bonus;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getBaseSalary() {
        return baseSalary;
    }

    public void setBaseSalary(int baseSalary) {
        this.baseSalary = baseSalary;
    }

    public int getBonus() {
        return bonus;
    }

    public void setBonus(int bonus) {
        this.bonus = bonus;
    }


    public Salary() {

    }

    public Salary(String name, int baseSalary, int bonus) {
        this.name = name;
        this.baseSalary = baseSalary;
        this.bonus = bonus;
    }

    public Salary build() {
        this.name = getRandomName(4);
        // 0-100隨機數
        this.baseSalary = (int)(100 * Math.random());
        // 0-5隨機數
        this.bonus = (int)(5 * Math.random());
        return this;
    }

    @Override
    public String toString() {
        return name + " " + baseSalary + " " + bonus;
    }

    /**
     * 生產Name隨機函數 4位a-z隨機
     * @param length
     * @return
     */
    private static String getRandomName(int length ){
        String base = "abcdefghijklmnopqrstuvwxyz";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for ( int i = 0; i < length; i++ ){
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}

第二步:編寫寫入方法

​ a) 第一種方式,使用Java的IO中BufferedWriter寫入文件this

/**
 * 寫入文件
 * @return
 * @throws IOException
 */
public static File writeBuffer() throws IOException {
    File file = new File(FILE_NAME);
    FileOutputStream fos = new FileOutputStream(file);
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
    int i = AMOUNT;
    while(i > 0) {
        Salary salary = new Salary().build();
        writer.write(salary.toString() + "\r\n");
        i --;
    }
    writer.close();
    fos.close();
    return file;
}

​ b) 第二種方式,使用JAVA的NIO中的FileChannel進行寫入編碼

/**
 * NIO進行寫入
 * @throws IOException
 */
private static void writeNIO() throws IOException {
    FileOutputStream fos = new FileOutputStream(FILE_NAME, true);
    FileChannel channel = fos.getChannel();
    int i = AMOUNT;
    StringBuffer content = new StringBuffer();
    while(i > 0) {
        Salary salary = new Salary().build();
        content.append(salary.toString()).append("\r\n");
        i --;
    }
    ByteBuffer buf = ByteBuffer.wrap(content.toString().getBytes());
    buf.put(content.toString().getBytes());
    buf.flip();
    channel.write(buf);
    channel.close();
    fos.close();

}

比較下來,單純從這個代碼的性能上講差不太多!

第三步:讀取並解析文件在進行排序

​ a) 經過JAVA的IO進行讀取:

/**
 * Java IO讀取文件的方式
 * @return
 * @throws Exception
 */
public static List<Salary> readFileIO() throws Exception {
    File file = new File(FILE_NAME);
    List<Salary> list = new ArrayList<>();
    InputStreamReader reader = new InputStreamReader(new FileInputStream(file)); // 創建一個輸入流對象reader
    BufferedReader br = new BufferedReader(reader); // 創建一個對象,它把文件內容轉成計算機能讀懂的語言
    String line = ""; // 每一行的內容
    int i = 1;
    while ((line = br.readLine()) != null) {
        String[] split = line.trim().split(" ");// .trim()能夠去掉首尾多餘的空格
        list.add(new Salary(split[0], Integer.valueOf(split[1]), Integer.valueOf(split[2]))); // 添加一個Salary實體
        i++;
    }
    reader.close();
    br.close();
    return list;
}

​ b) 經過JAVA的NIO讀取:

/**
 * JDK8 NIO讀取文件
 * @return
 * @throws Exception
 */
public static List<Salary> readFileNIO() throws Exception {
    List<Salary> list = new ArrayList<>();
    Files.lines(Paths.get(FILE_NAME)).forEach(line -> {
        String[] split = line.trim().split(" ");// .trim()能夠去掉首尾多餘的空格
        list.add(new Salary(split[0], Integer.valueOf(split[1]), Integer.valueOf(split[2]))); // 添加一個Salary實體
    });
    return list;
}

兩者比較下來:使用jdk1.8讀取更簡單,效率性能更高!

第四步:使用JDK8的Stream進行排序和截取

/**
 * 排序並獲取前十數據
 * @param salaries
 */
public static void sort(List<Salary> salaries) {
    Map<String, GroupSalary> result = new HashMap<>();
    salaries.forEach(salary -> {
        String shortName = salary.getName().substring(0, 2);
        GroupSalary groupSalary = null;
        List<Salary> salaryList = null;
        if (result.containsKey(shortName)) {
            groupSalary = result.get(shortName);
            salaryList = groupSalary.getSalaries();
        } else {
            groupSalary = new GroupSalary();
            salaryList = new ArrayList<>();
            groupSalary.setSalaries(salaryList);
        }
        salaryList.add(salary);
        groupSalary.setShortName(shortName);
        groupSalary.setTotal(groupSalary.getTotal() + salary.getBaseSalary() * 13 + salary.getBonus());
        result.put(shortName, groupSalary);
    });

    List<GroupSalary> r = result.entrySet().stream()
            .sorted((Map.Entry<String, GroupSalary> o1, Map.Entry<String, GroupSalary> o2) -> o2.getValue().getTotal() - o1.getValue().getTotal())
            .map(entry -> entry.getValue()).collect(Collectors.toList()).subList(0,10);

    r.forEach(groupSalary -> {
        System.out.println(groupSalary.getShortName() + " " + groupSalary.getTotal() + " " + groupSalary.getSalaries().size());
    });
}

同時將數據封裝在GroupSalary中

class GroupSalary {
    private List<Salary> salaries;
    private String shortName;
    private int total;

    public List<Salary> getSalaries() {
        return salaries;
    }

    public void setSalaries(List<Salary> salaries) {
        this.salaries = salaries;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }


}

到此若是寫入100W數據基本上1分鐘不到就能夠完成寫入和讀取,歡迎你們進行改寫和優化,具體代碼請去:

相關文章
相關標籤/搜索