遇到一道经典的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;
    }

}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值