遇到一道经典的java面试题
在文件 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面试题的更多相关文章
- OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)
摘要 本文先给出一个看似很简单实则有深意的Java笔试面试题,引出JDK内部的缓存. JDK内部的缓存,主要是为了提高Java程序的性能. 你能答对这道"看似简单,实则有深意"的J ...
- 一道经典的Java面试题:equals ,== 和hashcode()的区别
一句话区别:==比较的是内存地址,equals比较的是值内容 结论: 从以下三点展开: 基本数据类型.字符串.对象 对于基本数据类型:只有==,没有equals. 对于字符串:==比较的是内存地址,e ...
- 10个经典的Java面试题
这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...
- 10个经典的Java面试题集合
这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...
- 100多道经典的JAVA面试题及答案解析
面向对象编程(OOP) Java是一个支持并发.基于类和面向对象的计算机编程语言.下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改. 代码复用. 增强代码的可靠性和灵活性. 增加代码 ...
- OpenJDK源码研究笔记(二)-Comparable和Comparator2个接口的作用和区别(一道经典的Java笔试面试题)
Comparable和Comparator是JDK中定义的2个比较接口,很相似,但又有所不同. 这2个接口的作用和区别也是Java中的常见经典面试题. 下面我们就来详细介绍下这2个接口的定义.作用.区 ...
- 一道简单的 Java 笔试题,但值得很多人反思!
前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...
- 一道经典的js面试题
# 声明:学习编程语言最好的方式就是通过实例学习 ## 下面是我在博客上看到的一道js面试题,可以说非常经典,下面会以最简单的方式让你理解题目:```bashfunction Foo() { getN ...
- 15 道超经典大厂 Java 面试题!重中之重
从超高频的后端面试题出发,指明学习方向 大家好,我是鱼皮. 还记得我的老弟小阿巴么?他目前正值大一暑假,在家自学编程(刷短视频)中. 他整个大一期间基本都在学习前端.后来,我带他写了一次后端,结果就崩 ...
随机推荐
- bzoj 4173 打表???
没有任何思路,打表发现ans=phi(n)*phi(m)*n*m %%% popoqqq Orz 然而并没有看懂-- #include<cstdio> #include<cstrin ...
- BZOJ_1260_[CQOI2007]涂色paint _区间DP
BZOJ_1260_[CQOI2007]涂色paint _区间DP 题意: 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字 ...
- BZOJ_2743_[HEOI2012]采花_离线+树状数组
BZOJ_2743_[HEOI2012]采花_离线+树状数组 Description 萧芸斓是Z国的公主,平时的一大爱好是采花.今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花 .花园足够大 ...
- Heartbeat实现集群高可用热备
公司最近需要针对服务器实现热可用热备,这几天也一直在琢磨这个方面的东西,今天做了一些Heartbeat方面的工作,在此记录下来,给需要的人以参考. Heartbeat 项目是 Linux-HA 工程的 ...
- nodejs-5.1 ejs模板引擎
ejs官方文档:https://ejs.bootcss.com/ 1.什么是 EJS? "E" 代表 "effective",即[高效]. EJS 是一套简单的 ...
- XMR挖矿教程
XMR挖矿教程 XMR介绍 门罗币(Monero,代号XMR)是一个创建于2014年4月开源加密货币,它着重于隐私.分权和可扩展性.与自比特币衍生的许多加密货币不同,Monero基于CryptoNot ...
- 本地和svn都删除文件导致版本不同的问题
想要删除一个项目中的文件,同是要删除svn上的文件. 自己操作 1.直接右键删除了本地项目中的一个目录的模块 2.右键删除了库中svn中的这个目录 3.同步本地和svn上的代码 4.问题出现了,本地和 ...
- Nginx高并发优化方案
原网址: https://blog.csdn.net/HoeWang/article/details/81221463 一.一般来说nginx 配置文件中对优化比较有作用的为以下几项: 1. work ...
- C#调用Python脚本打印pdf文件
介绍:通过pdf地址先将文件下载到本地,然后调用打印机打印,最后将下载的文件删除. 环境:windows系统.(windows64位) windows系统中安装python3.6.2环境 资料: O ...
- 每日分享!JavaScript的鼠标事件(11个事件)
鼠标的11个事件 具体的事件解释如下: click:按下鼠标(通常是按下主按钮)时触发. dblclick:在同一个元素上双击鼠标时触发. mousedown:按下鼠标键时触发. mouseup:释放 ...