• 性能优化——算法优化


    背景

    因为某种原因,我们系统须要记录还有一个系统中一个表里的id

    可是。当我们记录完了以后,别人系统可能会删除那个表里的一些数据,这种话,我们这边就多了一些无效数据。所以,我们必须的找到这些无效的id,然后将其删除。

     

    開始。我们的实现是这样:我们将记录下来的全部id放在一个list里,然后传到还有一个系统,他将他们已经删除的id返回。详细处理代码例如以下:

    <pre name="code" class="java">public String findDeletedStuChooseCourseIds(List<String> stuChooseCourseIds) {
    	List<String> delIds = new ArrayList<String>();
    	// 循环遍历全部给定id,查看是否存在
    	for (String id : stuChooseCourseIds) {
    		StuChooseCourse stuChooseCourse = commonEao.get(StuChooseCourse.class, id);
    		if (null == stuChooseCourse) {
    			delIds.add(id);
    		}
    	}
    	return JsonUtils.toJson(delIds);
    }

    
    

    開始的时候,数据量比較小,并没有感觉到这种方法有什么问题。

    可是随着时间的推移。数据量不断添加。终于达到十几万条数据。问题也就随之而来了。这种方法的运行时间已经远远超出了我们的忍耐极限。居然5分钟都没有运行完,这个必须得优化。

    分析一下运行慢的原因。非常明显。循环里的查找数据费了时间,每循环一次,都须要去数据库中查找一次,这样能快就见鬼了。所以。必须降低与数据库的交互。于是代码变成了例如以下版本号:

    <pre name="code" class="java">public String findDeletedStuChooseCourseIds(List<String> stuChooseCourseIds) {
    	//获取全部stuchoosecourse的ids
    	String  nativeSql = "select id from tableName ";
    	List<String> list = commonEao.executeGetNativeSQL(nativeSql);
    	
    	stuChooseCourseIds.removeAll( list );
    	
    	return JsonUtils.toJson(stuChooseCourseIds);
    }

    
    

    这种话,仅仅须要跟数据库进行一次交互。并且使用的jdk的removeAll方法(一般jdk实现的方法,效率都还不错),效率应该会提高不少。于是,我满怀希望的进行測试,但结果还是让人难以接受,效率似乎并没有提高多少。

    分析一下原因。肯定是stuChooseCourseIds.removeAll(list )浪费了时间,由于我们使用的listarrayList。而arrayList在运行查找和删除操作时是比較费时间的。后来,我们换成了LinkedList,但结果还是一样。所以,我们必须换种思维方式了。于是。代码变成了例如以下版本号:

    <pre name="code" class="java">public String findDeletedStuChooseCourseIds(List<String> stuChooseCourseIds) {
    	List<String> delIds = new ArrayList<String>();
    	//获取全部stuchoosecourse的ids
    	String  nativeSql = "select id from tableName ";
    	List<String> list = commonEao.executeGetNativeSQL(nativeSql);
    	//将list中的id放到HashSet中
    	HashSet<String> dbSet = new HashSet<String>();
    	for(String id : list){
    		dbSet.add(id);
    	}
    	
    	//将stuChooseCourseIds中的id放到dbSet中
    	for(String givenId : stuChooseCourseIds){
    		if(dbSet.add(givenId)){
    			delIds.add(givenId);
    		}
    	}
    	
    	return JsonUtils.toJson(delIds);
    }
    


    
    

    这里使用HashSet来处理。首先,一旦用到Hash,查找效率定然会大幅度提升。其次,巧妙的利用了Set中元素不可反复的特性。这样一来,终于的运行效率提升了20多倍,原本五分钟都结束不了的方法,如今仅须要十几秒。这个结果还是让人比較惬意的。

     

    数据量小的时候,问题不明显。等数据量多了以后,问题出来了。这个问题也告诉我们,凡事都要用发展的眼光看问题。

    既然如此。那么让我们继续看最后一版的代码。

     

    如今数据量是十几万,假设时间再向后推移。数据量变成百万,试想将百万的数据放在一个list里,暂且不说效率的问题。请问你的内存受得了吗?答案是肯定的,内存会被撑爆。

    那么,这个问题必须解决。

    于是,终于的版本号例如以下:

    <pre name="code" class="java">public String findDeletedStuChooseCourseIds(List<String> stuChooseCourseIds,String schoolCalendarId) {
    	List<String> delIds = new ArrayList<String>();
    	//获取全部stuchoosecourse的ids
    	String  nativeSql = "select id from tableName where schoolcalendarid='"+schoolCalendarId+"'";
    	List<String> list = commonEao.executeGetNativeSQL(nativeSql);
    	//将list中的id放到HashSet中
    	HashSet<String> dbSet = new HashSet<String>();
    	for(String id : list){
    		dbSet.add(id);
    	}
    	
    	//将stuChooseCourseIds中的id放到dbSet中
    	for(String givenId : stuChooseCourseIds){
    		if(dbSet.add(givenId)){
    			delIds.add(givenId);
    		}
    	}
    	
    	return JsonUtils.toJson(delIds);
    }
    


    
    

    方法又加了一个參数——学年学期,每一学期产生的数据基本上是不变的,这样一来。不管多久之后。方法的运行效率都不会再受影响。

     

    通过这次的优化,让我真正感受到了数据结构的魅力。骚年。有时间好好学习一下数据结构吧!

  • 相关阅读:
    自考新教材-p173_3(1)
    自考新教材-p148_5(2)
    自考新教材-p148_5(1)
    自考新教材-p148_4
    自考新教材-p147_3
    自考新教材-p146_4(2)
    python 模块 chardet报错解决方法:下载及介绍
    第 52 讲:论一只爬虫的自我修养
    第 51 讲: _name_属性
    Python 培训第一讲
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6848665.html
Copyright © 2020-2023  润新知