在文件 nameList.txt 中按下图格式存放着超过50万人的姓名与身份证信息。请使用您熟悉的编程语言(Java或C/C++)编写一段程序, 将出生日期落在1995年1月1日与1999年12月31日之间的个人信息取出,按年龄从大到小排列并输出到另一个txt文件中。 请重点考虑程序的健壮性和排序效率

小生想到思路:

  1. 先读取文本内容;

  2. 将头信息读取出来,并记录住;

  3. 将真实数据按照行进行读取并封装到 javabean 中:每读取一行,将这行的数据用javabean封装,将这个javabean添加到 list 列表中:

  4. 将得到的 list 列表进行排序,按照出生日期排序,这题正好:出生日期可以作为数字来看待,数字小的就是出生早的;

  5. 将头信息和 list 列表再输出到指定文件中

注意:

题目是要求50万条数据记录进行读取排序,所以一定要想到包装类IO

还有就是要考虑健壮性和排序效率,健壮性,最完美的设计就是无论传递给程序什么javabean,程序都能把读到的数据封装成这个javabean

小生想到的就是动态代理和泛型。

具体实现代码如下(小生这里没有采用包装类了):

 package com.hy.demo;

 import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import com.hy.demo.UserComparator.SortType; public class DemoTest {
public static void main(String[] args) {
String inpathName = "D:/Workspaces/eclipse-marks-2/hire/src/name_list.txt"; String content = getFileContent(inpathName); // 得到用户数据列表
List<User> userList = getList(content, 3,"19950101","19991231");
// 按照出生日期排序用户列表
String context = orderByUser(userList, SortType.ASC);
// 获取头信息
String header = getHeader(content, 3);
String outpathName = "D:/Workspaces/eclipse-marks-2/hire/src/a.txt";
write(header, context, outpathName);
} public static void write(String header,String context,String outPathName) {
FileOutputStream fos =null;
try {
fos = new FileOutputStream(outPathName);
fos.write(header.getBytes());
fos.write(context.getBytes()); fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos!=null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} } /**
* 对用户列表排序,并输出成文本格式
* @param list
* @param sortType ASC:按照出生日期升序,DESC:按照出生降序
* @return
*/
public static String orderByUser(List<User> list,SortType sortType) {
if(list!=null && list.size()>0) {
Collections.sort(list, new UserComparator(sortType));
StringBuffer sb = new StringBuffer(); for(int i=0;i<list.size();i++) {
User user = list.get(i);
sb.append(user.getName()).append(" \t\t");
sb.append(user.getGener()).append("\t\t");
sb.append(user.getIdCard()).append("\t\t");
sb.append(user.getAddress()).append("\r\n");
}
return sb.toString();
}
return null;
} /**
* 读取文本,获取数据源
*
* @param path
* @return
*/
public static String getFileContent(String path) {
File file = new File(path);
// 分配新的直接字节缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
StringBuffer stringBuffer = new StringBuffer(1024);
try {
FileInputStream fileInputStream = new FileInputStream(file);
// 用于读取、写入、映射和操作文件的通道。
FileChannel fileChannel = fileInputStream.getChannel();
// 编码字符集和字符编码方案的组合,用于处理中文,可以更改
Charset charset = Charset.forName("UTF-8");
while (fileChannel.read(byteBuffer) != -1) {
// 反转此缓冲区
byteBuffer.flip();
CharBuffer charBuffer = charset.decode(byteBuffer);
stringBuffer.append(charBuffer.toString());
byteBuffer.clear();
}
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.toString();
} /**
* 获取数据列表
* @param <T>
* @param content
* @param num 指定头信息含有多少行
* @return
*/
public static List getList(String content, int num,String start, String end) { // 将文本行信息按照行截取
String[] strs = content.split("\r\n"); if(num>strs.length) {
throw new RuntimeException("文本头行数参数不能大于文本总行数!");
} // 接收数据,按照行接收
List<User> list = new ArrayList<User>();
Integer date;
for (int i = num; i < strs.length; i++) {
// 将每一行的数据封装到User对象中
String[] userParams = strs[i].split("\t\t");
User user = new User();
user.setName(userParams[0]);
user.setGener(userParams[1]);
user.setIdCard(userParams[2]);
user.setAddress(userParams[3]);
// 将每一行数据添加到列表中 // 选择出生日期区间
if(start!=null&&!"".equals(start) && end!=null&&!"".equals(end)) {
date = Integer.parseInt(user.getIdCard().substring(6, 14));
if(date>= Integer.parseInt(start)&&date<=Integer.parseInt(end) ) {
list.add(user);
}
}
}
return list;
} /**
* 获取头信息
* @param context 指定要获取的文本内容
* @param num 指定获前几行
* @return
*/
public static String getHeader(String context, int num) {
// 将文本行信息按照行截取
String[] strs = context.split("\r\n");
// 接收头信息
StringBuffer headStringBuffer = new StringBuffer(); for (int i = 0; i < num; i++) {
headStringBuffer.append(strs[i]).append("\r\n");
}
// 获取头信息
return headStringBuffer.toString();
} }

javabean封装类:

public class User {
private String name;
private String gener;
private String idCard;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGener() {
return gener;
}
public void setGener(String gener) {
this.gener = gener;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [name=" + name + ", gener=" + gener + ", idCard=" + idCard + ", address=" + address + "]";
} }

javabean比较器:

public class UserComparator implements Comparator<User> {

    public enum SortType {
ASC, DESC
} public UserComparator(SortType sortType) {
this.sortType = sortType;
} private SortType sortType; @Override
public int compare(User o1, User o2) {
int o1Date = Integer.parseInt(o1.getIdCard().substring(6, 14));
int o2Date = Integer.parseInt(o2.getIdCard().substring(6, 14));
switch (sortType) {
case ASC:
if (o1Date > o2Date) {
return 1;
} else if (o1Date < o2Date) {
return -1;
}
break;
case DESC:
if (o1Date > o2Date) {
return -1;
} else if (o1Date > o2Date) {
return 1;
}
break; default:
break;
}
return 0;
} }

读者们,如果有更好思路和细节处理,欢迎留言讨论,谢谢!

遇到一道经典的java面试题的更多相关文章

  1. OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)

    摘要 本文先给出一个看似很简单实则有深意的Java笔试面试题,引出JDK内部的缓存. JDK内部的缓存,主要是为了提高Java程序的性能. 你能答对这道"看似简单,实则有深意"的J ...

  2. 一道经典的Java面试题:equals ,== 和hashcode()的区别

    一句话区别:==比较的是内存地址,equals比较的是值内容 结论: 从以下三点展开: 基本数据类型.字符串.对象 对于基本数据类型:只有==,没有equals. 对于字符串:==比较的是内存地址,e ...

  3. 10个经典的Java面试题

    这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...

  4. 10个经典的Java面试题集合

    这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...

  5. 100多道经典的JAVA面试题及答案解析

    面向对象编程(OOP) Java是一个支持并发.基于类和面向对象的计算机编程语言.下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改. 代码复用. 增强代码的可靠性和灵活性. 增加代码 ...

  6. OpenJDK源码研究笔记(二)-Comparable和Comparator2个接口的作用和区别(一道经典的Java笔试面试题)

    Comparable和Comparator是JDK中定义的2个比较接口,很相似,但又有所不同. 这2个接口的作用和区别也是Java中的常见经典面试题. 下面我们就来详细介绍下这2个接口的定义.作用.区 ...

  7. 一道简单的 Java 笔试题,但值得很多人反思!

    前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...

  8. 一道经典的js面试题

    # 声明:学习编程语言最好的方式就是通过实例学习 ## 下面是我在博客上看到的一道js面试题,可以说非常经典,下面会以最简单的方式让你理解题目:```bashfunction Foo() { getN ...

  9. 15 道超经典大厂 Java 面试题!重中之重

    从超高频的后端面试题出发,指明学习方向 大家好,我是鱼皮. 还记得我的老弟小阿巴么?他目前正值大一暑假,在家自学编程(刷短视频)中. 他整个大一期间基本都在学习前端.后来,我带他写了一次后端,结果就崩 ...

随机推荐

  1. BZOJ_1257_ [CQOI2007]余数之和sum_数学

    BZOJ_1257_ [CQOI2007]余数之和sum_数学 题意:给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值. 分 ...

  2. 使用FileUpload实现Servlet的文件上传

    简介 FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下的文件上传功能. FileUpload链接 FileUpload 是基于Apache的Commons ...

  3. MySQL(七)DQL之分组查询

    一.语法 select 分组函数,分组后的字段from 表[where 筛选条件]group by 分组的字段[having 分组后的筛选][order by 排序列表] 二.特点 分组前筛选:whe ...

  4. 基于 HTML5 的 WebGL 3D 版俄罗斯方块

    前言 摘要:2D 的俄罗斯方块已经被人玩烂了,突发奇想就做了个 3D 的游戏机,用来玩俄罗斯方块...实现的基本想法是先在 2D 上实现俄罗斯方块小游戏,然后使用 3D 建模功能创建一个 3D 街机模 ...

  5. 【转】干货,Kubernetes中的Source Ip机制。

    准备工作 你必须拥有一个正常工作的 Kubernetes 1.5 集群,用来运行本文中的示例.该示例使用一个简单的 nginx webserver 回送它接收到的请求的 HTTP 头中的源 IP 地址 ...

  6. Gatling简单测试SpringBoot工程

    前言 Gatling是一款基于Scala 开发的高性能服务器性能测试工具,它主要用于对服务器进行负载等测试,并分析和测量服务器的各种性能指标.目前仅支持http协议,可以用来测试web应用程序和RES ...

  7. 设计一下类似SpringIoC的注入工具~Lind.DI

    通过注解(特性)的方式进行对象的注册与注入,方便,灵活! 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入! spring ioc工作的过程大致为,统一的注册组件, ...

  8. 搜狗输入法与VS快捷键有冲突_处理办法

    前言:搜狗输入法是大家常用的文字输入工具,但是在开启输入法的时候,VS的一些快捷键无法正常使用,如智能提示快捷键:Ctrl+.,这就非常尴尬了,除非把输入法切换成英文或者卸载搜狗改别的输入法,一个是切 ...

  9. c#发送邮件,可发送多个附件

    1:创建SendMail类 2:调用方法 SendMail send = new SendMail("123456@qq.com", "123456@163.com&qu ...

  10. 学习python的第三天

    4.28日总结 一.关于python 1.交互式 说一句解释一句 2.命令行式 1.编写文件并且保存 2.打开python解释器,在pyrhon中打开文本,读入内存(python打开的时候,翻译不是瞬 ...