专业的JAVA编程教程与资源

网站首页 > java教程 正文

JAVA8新特性快速写入和读取文件(jdk8新特性)

temp10 2024-10-01 22:25:11 java教程 14 ℃ 0 评论


话不多说,先看题:

JAVA8新特性快速写入和读取文件(jdk8新特性)

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

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() + "\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分钟不到就可以完成写入和读取,欢迎大家进行改写和优化。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表