在文件 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. Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.

    报错信息:Description Resource Path Location Type Cannot change version of project facet Dynamic Web Modu ...

  2. 循环神经网络之LSTM和GRU

    看了一些LSTM的博客,都推荐看colah写的博客<Understanding LSTM Networks> 来学习LSTM,我也找来看了,写得还是比较好懂的,它把LSTM的工作流程从输入 ...

  3. STM32学习笔记(二):GPIO口工作原理

    STM32每个IO口具有7个寄存器来控制,每个IO口都可以自由进行编程控制,我们编程实际上控制的是通过控制那7个寄存器来控制我们的IO口,我们可以通过编程控制IO口,把IO口配置成如下八种模式: 1. ...

  4. 原生JS封装 toast 弹层,自动关闭

    由于公司业务需求,要一个公共toast ,下面是自己封装的一个. css: .toast { text-align: center; min-height: 70px; width: 220px; c ...

  5. Java语言编程 - Java历史简介

    1.1 Sun公司 介绍Java的历史之前,先介绍一下Java语言的缔造公司,Sun公司,Sun公司的全称是:Stanford University Network.值得一提的是,Sun公司从1982 ...

  6. java实现开根号算法

    public static void main(String[] args) { long start = System.currentTimeMillis(); double target=9876 ...

  7. Python 转化成 PB 格式数据

    一.概述 Protocol Buffers 是 Google 公司开发的一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或 RPC 数据交换格式.可用于通讯 ...

  8. selinux学习

    一.基本概念 1.TE模型的安全上下文 所有的操作系统访问控制都基于主体.客体,以及与他们相关的访问控制属性. 在selinux中,访问控制属性叫做安全上下文.所有对象(文件.进程间通信通道.套接字. ...

  9. Postgre Sql获取最近一周、一月、一年日期函数

    使用Postgre Sql获取近一周.一年.一月等系统函数调用如下,使用方面相对于Ms Sql server 容易了许多. --当前时间 select now(); --current_timesta ...

  10. AES加密然后ajax传输数据

    最近做的一个项目,需要对传输的参数进行aes加密,所以就顺便的了解了一下,因为这种东西,肯定都是有写好的,现成的,所有这里就简单的记录一下,方便以后自己和大家查找. 首先附上百度的关于AES的百度百科 ...