摘要:快速写入和读取文件话不多说,先看题随机生成的记录,如,每行一条记录,总共万记录,写入文本文件编码,然后读取文件,的前两个字符相同的,其年薪累加,比如,万,个人,最后做排序和分组,输出年薪总额最高的组万,人万,人位随机,随机随机,年薪总
JAVA8快速写入和读取文件?
话不多说,先看题:
随机生成 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对象里面包含有name,baseSalary, 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() + " "); 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(" "); 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 ListreadFileIO() throws Exception { File file = new File(FILE_NAME); List 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 ListreadFileNIO() throws Exception { List 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(Listsalaries) { Map result = new HashMap<>(); salaries.forEach(salary -> { String shortName = salary.getName().substring(0, 2); GroupSalary groupSalary = null; List 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 r = result.entrySet().stream() .sorted((Map.Entry o1, Map.Entry 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 Listsalaries; private String shortName; private int total; public List getSalaries() { return salaries; } public void setSalaries(List 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分钟不到就可以完成写入和读取,欢迎大家进行改写和优化,具体代码请去:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72504.html
摘要:示例字符串数值算术和文件原文译者飞龙协议大量的教程和文章都涉及到中最重要的改变,例如表达式和函数式数据流。不仅仅是字符串,正则表达式模式串也能受益于数据流。 Java 8 API 示例:字符串、数值、算术和文件 原文:Java 8 API by Example: Strings, Numbers, Math and Files 译者:飞龙 协议:CC BY-NC-SA 4.0 ...
摘要:基本输入流输入流类中包含两类功能输入流的两大功能读取流中字节数据的功能是通过方法来完成。基本输出流与类相对应的类表示基本的输出流,用来把数据从程序输出到其他地方。 一堆废话(赶快跳过) 在我们的日常开发中 I/O 涉及到我们开发的方方面面,虽然早在 JDK1.5 就新增了 NIO的概念,但是 java.io 的使用以及技巧在我们的日常开发中还是占据很高的比重。 概念(不看也行) ...
摘要:实战读书笔记第一章从方法传递到接着上次的,继续来了解一下,如果继续简化代码。去掉并且生成的数字是万,所消耗的时间循序流并行流至于为什么有时候并行流效率比循序流还低,这个以后的文章会解释。 《Java8实战》-读书笔记第一章(02) 从方法传递到Lambda 接着上次的Predicate,继续来了解一下,如果继续简化代码。 把方法作为值来传递虽然很有用,但是要是有很多类似与isHeavy...
摘要:提升自己,方便他人。其实一份文档,说到底是为自己减轻工作量。总结总结起来,我们在提供一个通用包的时候,应该考虑以下七个点文档。支持的类反射获取参数名面向接口编程。一个注解,快速整合 声明:本文属原创文章,首发于公号程序员自学之道,转载请注明出处 遇到槽点 开发实践中,对于开发一个 jar 包,很多人都只是完成功能,只要功能使用没问题,就算是完事了,但其实远远不够。当用户使用 jar 包...
摘要:和之间存在单向一对一关系,即通过指定的,总能找到唯一的确定的。从中取出数据时,只要给出指定的,就可以取出对应的。有时也称为字典,或关联数组。采用定制排序时不要求的实现接口中判断两个相等的标准是两个通过方法返回,即认为这两个是相等的。 map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,key和value...
阅读 2839·2021-07-30 15:30
阅读 539·2019-08-30 15:55
阅读 1606·2019-08-26 17:04
阅读 616·2019-08-26 11:36
阅读 2044·2019-08-26 10:58
阅读 3535·2019-08-23 14:34
阅读 1499·2019-08-22 18:48
阅读 2502·2019-08-21 17:51