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

}

如果有更好思路和細節處理,歡迎留言討論,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章