美文网首页
【码歌】JAVA8实用——快速写入和读取文件

【码歌】JAVA8实用——快速写入和读取文件

作者: 坑王老薛 | 来源:发表于2018-12-05 09:24 被阅读269次
    Java8快速读取和写入文件.png

    话不多说,先看题:

    随机生成 Salary {name, baseSalary, bonus }的记录,如“wxxx,10,1”,每行一条记录,总共1000万记录,写入文本文件(UFT-8编码), 然后读取文件,name的前两个字符相同的,其年薪累加,比如wx,100万,3个人,最后做排序和分组,输出年薪总额最高的10组:

    wx 200万 10人
    lt 180万 8人
    ... ... ...

    name 4位a-z随机,baseSalary [0,100]随机 bonus[0-5]随机 ,年薪总额 = baseSalary*13 + bonus。

    思路:

    第一步:先编写一个Salary对象

    里面包含有namebaseSalary, bounus属性,然后编写一个构造器,重写toString()方法方便序列化数据,同时编写构建Salary对象的方法build()

    /**
     *  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写入文件

    /**
     * 写入文件
     * @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分钟不到就可以完成写入和读取,欢迎大家进行改写和优化。

    相关文章

      网友评论

          本文标题:【码歌】JAVA8实用——快速写入和读取文件

          本文链接:https://www.haomeiwen.com/subject/naticqtx.html