1.在編寫程序對數據處理的時候我們經常會使用到list和map集合,有些時候我們存到集合里的數據只是暫時性的,在驗證完或者使用完之后盡量對list或者map清空,及list.clear()后者map.clear(),
這樣我們可以大大減輕服務器內存被占用率,特別是處理數據量比較大的驗證以及過濾的時候,對於程序的性能以及運行速度都是影響很大的。
2.程序中我們經常會遇見把數據存到excel中然后經過中間件進入數據庫中,這樣的數據需要經過一系列的驗證到最后只是把正確的數據保存到數據庫中,錯誤的直接過濾掉,而經過驗證的時候我們難免會遇見本身重復校驗這塊,比如你導入1W條數據,而我們比對是不是拿其中一個和剩下所有的比較,不重復了保存到一個集合中,重復的保存到一個集合中,這樣有沒有考慮到比對的次數?1W*1W是什么概念?上億次呢,所以同樣是寫程序有的人寫出來的代碼運行速度很快,而有的人寫的代碼程序運行很慢,雖然功能都能實現,但是在數據量大的時候二者誰優誰劣就見分曉了。
3.例子:以下舉一個簡單的例子,寫在這里以后沒事的時候看看,同時提醒自己和大家寫程序要養成一個良好的習慣,這點很重要。
//批量導入學生信息
public String batchImport(){
long startTime = System.currentTimeMillis();
SchoolInfoDTO school = (SchoolInfoDTO) request.getSession().getAttribute("schoolInfo");
//文件導入失敗
if(filePath==null){
request.setAttribute("msg", "請先選擇要導入數據的文件!");
}else{
try {
/**
* 1、讀取Excel中的數據
*/
long t1 = System.currentTimeMillis();
HashMap<String, ArrayList<Ac56TempDTO>> resultMap = readXls(filePath);
long t2 = System.currentTimeMillis();
System.out.println("---------------------------------------------------------------------------");
System.out.println("Excel讀取時間:"+(t2-t1)/1000+"秒");
System.out.println("---------------------------------------------------------------------------");
if(null==resultMap){
request.setAttribute("msg", "導入文件存在問題,請確認文件格式是否正確!");
}else{
List<Ac56TempDTO> rightList = resultMap.get("right");
List<Ac56TempDTO> wrongList = resultMap.get("wrong");
int totalCount = (rightList==null?0:rightList.size()) + (wrongList==null?0:wrongList.size());
if(totalCount>5000){ //控制excel數據的數量
request.setAttribute("msg", "一次最多導入5000條數據。當前導入的數據大於5000條,請分多次導入!");
}else{
List<Ac56TempDTO> resultList = new ArrayList<Ac56TempDTO>();//待保存到數據庫里的結果集
/**
* 2、刪除ac56temp臨時表中的數據
*/
long t3=System.currentTimeMillis();
ac56Tempvs.deleteAc56TempTA(school.getAab001());
long t4=System.currentTimeMillis();
System.out.println("---------------------------------------------------------------------------");
System.out.println("刪除數據時間:"+(t4-t3)/1000+"秒");
System.out.println("---------------------------------------------------------------------------");
/**
* 3、將不符合Excel填寫規范的數據放入結果集中並清除內存中的錯誤格式數據
*/
resultList.addAll(wrongList);
wrongList.clear();
/**
* 4、獲取重復數據並放入removeUsers結果集,然后放入resultList結果集,然后清除removeUsers以及內存中的removeUsers對象
*/
long t5=System.currentTimeMillis();
List<Ac56TempDTO> removeUsers = duplicateList(rightList);
resultList.addAll(removeUsers);//把重復的數據添加到結果集里面去
rightList.removeAll(removeUsers);//正確數據集合中剔除數據重復的集合 剩余的即是正確的數據
removeUsers.clear();//清除removeUsers以及內存中的removeUsers對象
long t6=System.currentTimeMillis();
System.out.println("---------------------------------------------------------------------------");
System.out.println("取出重復數據時間:"+(t6-t5)/1000+"秒");
System.out.println("---------------------------------------------------------------------------");
/**
* 5、判斷年級和對應班級在本校是否存在,如果不存在,則記錄下來放入resultList中,然后清除rightList中的list1和內存中的list1以及相關的map
*/
long nb=System.currentTimeMillis();
//將年級和班級作為key,獲取學校下的班級年級信息
HashMap<String, String> gradeClassName = new HashMap<String, String>();
for(Ac56TempDTO dto:rightList){
gradeClassName.put(dto.getBac053()+","+dto.getBac054(), school.getAab001());
}
//根據年級、班級和學校編號查詢年級班級信息
HashMap<String, String> ac56Map = ac56vs.isGradeAndClassEmpty(gradeClassName);
List<Ac56TempDTO> list1 = new ArrayList<Ac56TempDTO>();
for(Ac56TempDTO dto:rightList){
String key = dto.getBac053()+","+dto.getBac054();
if(ac56Map.containsKey(key)&&"0".equals(ac56Map.get(key))){
dto.setDatastate("0");
dto.setErrormsg("年級和對應班級在本校中不存在!");
list1.add(dto);
}
}
//將年級和對應班級不存在的記錄更新放到結果集中resultList,同時,清除rightList中的list1和內存中的list1以及相關的map
resultList.addAll(list1);
rightList.removeAll(list1);
list1.clear();
gradeClassName.clear();
ac56Map.clear();
long bj=System.currentTimeMillis();
System.out.println("----------------------------------------------------------------");
System.out.println("年級班級檢查耗時:"+(bj-nb)/1000+"秒");
System.out.println("----------------------------------------------------------------");
/**
* 6、驗證學生是否已經在學校網上辦事系統中參保登記了
*/
long t7=System.currentTimeMillis();
List<Ac56TempDTO> studentList = new ArrayList<Ac56TempDTO>();
for(Ac56TempDTO dto:rightList){
List<Ac56> ac56List= ac56vs.isStudentEmpty(dto.getAac002());
if(ac56List.size()>0){
String aab004 = ac56List.get(0).getAab004();
aab004 = aab004.substring(0, aab004.indexOf("("));
dto.setErrormsg("該生已在"+aab004+"進行了參保登記");
dto.setDatastate("0");
studentList.add(dto);
}
}
resultList.addAll(studentList);
rightList.removeAll(studentList);
studentList.clear();
long t8=System.currentTimeMillis();
System.out.println("-------------------------------------------------------------");
System.out.println("驗證網上辦事參保登記學生情況用時:"+(t8-t7)/1000+"秒");
System.out.println("-------------------------------------------------------------");
/**
* 7、查看此學生在ahsimis.ac02中是否有除了居民醫保以外的正在參保的記錄,有這樣的學生,要記錄下來放入oldList中
*/
long t9=System.currentTimeMillis();
List<Ac56TempDTO> oldList = checkAC01(rightList);
resultList.addAll(oldList);
rightList.removeAll(oldList);
oldList.clear();
long t10 =System.currentTimeMillis();
System.out.println("--------------------------------------------------------------");
System.out.println("ESB耗時:"+(t10-t9)/1000+"秒");
System.out.println("--------------------------------------------------------------");
/**
* 導入結束
*/
if(resultList.size()>0){
int count=0;
/*記錄正確的數據條數*/
for(int i=0;i<resultList.size();i++){
if("1".equals(resultList.get(i).getDatastate())){
count++;
}
}
long t11 =System.currentTimeMillis();
ac56Tempvs.insertStudent(resultList);
long t12 =System.currentTimeMillis();
System.out.println("--------------------------------------------------------------");
System.out.println("插入數據庫耗時:"+(t12-t11)/1000+"秒");
System.out.println("--------------------------------------------------------------");
request.setAttribute("msg", "導入完成!共導入"+resultList.size()+"條數據,其中正確數據"+ count +"條。");
}else{
request.setAttribute("msg", "無數據,請核對表格!");
}
}
}
} catch (Exception e) {
request.setAttribute("msg", "導入學生信息出錯,請檢查文件數據格式是否與給定的模板完全一致!");
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("--------------------------------------------------------------");
System.out.println("導入總耗時:"+(endTime-startTime)/1000+"秒");
return SUCCESS;
}
/**
* 查找重復數據
* @param alist:待去重對象
* @return:返回重復的list
*/
public ArrayList<Ac56TempDTO> duplicateList(List<Ac56TempDTO> alist) {
HashMap<String, String> map = new HashMap<String, String>();
ArrayList<Ac56TempDTO> duplicateList =new ArrayList<Ac56TempDTO>();
//判斷身份證號是否重復,如果重復了,就給相應的key賦aac002值,否則賦空值
for(int i=0;i<alist.size();i++){
String aac002 = alist.get(i).getAac002();
if(map.containsKey(aac002)){
map.put(aac002, aac002);
}else{
map.put(aac002, "");
}
}
//取出身份證號重復的list集合
for(int i=0;i<alist.size();i++){
Ac56TempDTO dto =alist.get(i);
if(map.containsValue(dto.getAac002())){
dto.setDatastate("0");
dto.setErrormsg("該身份證號重復出現多次!");
duplicateList.add(dto);//里面放的都是數據重復的集合
}
}
map.clear();
return duplicateList;
}
/**
* 讀取Excel文件
* @param path
* @return List<Ac56TempDTO>
* @throws Exception
*/
private HashMap<String,ArrayList<Ac56TempDTO>> readXls(File path) throws Exception {
SchoolInfoDTO school = (SchoolInfoDTO) request.getSession().getAttribute("schoolInfo");
InputStream is = new FileInputStream(path);
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is);
Ac56TempDTO dto = null;
ArrayList<Ac56TempDTO> rightList = new ArrayList<Ac56TempDTO>();
ArrayList<Ac56TempDTO> wrongList = new ArrayList<Ac56TempDTO>();
HashMap<String,ArrayList<Ac56TempDTO>> resultMap = new HashMap<String,ArrayList<Ac56TempDTO>>();
// 讀取工作表Sheet
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(0);
if (hssfSheet == null) {
return null;
}
int totalRows = hssfSheet.getPhysicalNumberOfRows()-1;
// 循環行Row
for (int rowNum = 1; rowNum <=totalRows ; rowNum++) {
HSSFRow hssfRow = hssfSheet.getRow(rowNum);
if (hssfRow == null)continue;
dto = new Ac56TempDTO();
//0姓名
HSSFCell xm = hssfRow.getCell(0);
dto.setAac003(ExcelUtils.getValue(xm));
//1身份證:因為可能包含小寫字母x,必須轉換成大寫的X
HSSFCell sfz = hssfRow.getCell(1);
String aac002 = ExcelUtils.getValue(sfz);
if(!"".equals(StringUtils.ObjectToString(aac002))){
aac002 = aac002.toUpperCase();
}
dto.setAac002(aac002);
//2個人身份
HSSFCell grsf = hssfRow.getCell(2);
dto.setAac012(ExcelUtils.getValue(grsf));
//3所在年級
HSSFCell sznj = hssfRow.getCell(3);
dto.setBac053(ExcelUtils.getValue(sznj));
//4所在班級
HSSFCell szbj = hssfRow.getCell(4);
dto.setBac054(ExcelUtils.getValue(szbj));
//5家庭聯系電話
HSSFCell lxdh = hssfRow.getCell(5);
dto.setAae005(ExcelUtils.getValue(lxdh));
//6低保標識
HSSFCell db = hssfRow.getCell(6);
dto.setBac048(ExcelUtils.getValue(db));
//7殘疾標識
HSSFCell cjbs = hssfRow.getCell(7);
dto.setBac049(ExcelUtils.getValue(cjbs));
//8大病標識
HSSFCell dbbs = hssfRow.getCell(8);
dto.setBac041(ExcelUtils.getValue(dbbs));
//9三無標識
HSSFCell swbs = hssfRow.getCell(9);
dto.setBac042(ExcelUtils.getValue(swbs));
//默認添加字段:單位編號、繳費方式
dto.setAab001(school.getAab001());
dto.setBac044("3");
/*只要身份證號為空,就退出循環*/
if("".equals(StringUtils.ObjectToString(dto.getAac002()))){
break;
}else {
if((dto.getAac002().length() !=18) ||!CardUtils.isValidate18Idcard(dto.getAac002())){
//身份證合法性驗證1
dto.setErrormsg("身份證號不合法,必須為18位的有效身份證號");
dto.setDatastate("0");
wrongList.add(dto);
}else if("".equals(dto.getAac012())||(!"92".equals(dto.getAac012())&&!"94".equals(dto.getAac012()))){
dto.setErrormsg("個人身份必須為92或94");
dto.setDatastate("0");
wrongList.add(dto);
}else if("".equals(dto.getBac053())||dto.getBac053().length()>20){
dto.setErrormsg("年級不能為空,且長度不能大於20");
dto.setDatastate("0");
wrongList.add(dto);
}else if("".equals(dto.getBac054())||dto.getBac054().length()>20){
//所在班級不能為空
dto.setErrormsg("班級不能為空,且長度不能大於20");
dto.setDatastate("0");
wrongList.add(dto);
}else if("".equals(dto.getAae005())||dto.getAae005().length()>20){
//家庭聯系電話長度不能大於20
dto.setErrormsg("家庭聯系電話不能為空,且長度不能大於20");
dto.setDatastate("0");
wrongList.add(dto);
}else if(!"0".equals(dto.getBac048())&&!"1".equals(dto.getBac048())){
//低保標識:0否,1是
dto.setErrormsg("低保標識只能填0或1");
dto.setDatastate("0");
wrongList.add(dto);
}else if(!"0".equals(dto.getBac049())&&!"1".equals(dto.getBac049())){
//殘疾標識:0否,1是
dto.setErrormsg("殘疾標識只能填0或1");
dto.setDatastate("0");
wrongList.add(dto);
}else if(!"0".equals(dto.getBac041())&&!"1".equals(dto.getBac041())){
//大病標識:0否,1是
dto.setErrormsg("大病標識只能填0或1");
dto.setDatastate("0");
wrongList.add(dto);
}else if(!"0".equals(dto.getBac042())&&!"1".equals(dto.getBac042())){
//三無標識:0否,1是
dto.setErrormsg("三無標識只能填0或1");
dto.setDatastate("0");
wrongList.add(dto);
}else{
rightList.add(dto);
}
}
}
resultMap.put("right", rightList);
resultMap.put("wrong", wrongList);
return resultMap;
}