java优化算法_[Java教程]性能优化——算法优化

[Java教程]性能优化——算法优化

0 2014-06-14 17:00:43

背景

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

开始,我们的实现是这样:我们将记录下来的所有id放在一个list里,然后传到另一个系统,他将他们已经删除的id返回。具体处理代码如下:

public String findDeletedStuChooseCourseIds(List stuChooseCourseIds) {

List delIds = new ArrayList();

// 循环遍历所有给定id,查看是否存在

for (String id : stuChooseCourseIds) {

StuChooseCourse stuChooseCourse = commonEao.get(StuChooseCourse.class, id);

if (null == stuChooseCourse) {

delIds.add(id);

}

}

return JsonUtils.toJson(delIds);

}

开始的时候,数据量比较小,并没有感觉到这个方法有什么问题。但是随着时间的推移,数据量不断增加,最终达到十几万条数据,问题也就随之而来了。这个方法的执行时间已经远远超出了我们的忍耐极限,竟然5分钟都没有执行完,这个必须得优化。

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

public String findDeletedStuChooseCourseIds(List stuChooseCourseIds) {

//获取所有stuchoosecourse的ids

String  nativeSql = "select id from tableName ";

List list = commonEao.executeGetNativeSQL(nativeSql);

stuChooseCourseIds.removeAll( list );

return JsonUtils.toJson(stuChooseCourseIds);

}

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

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

public String findDeletedStuChooseCourseIds(List stuChooseCourseIds) {

List delIds = new ArrayList();

//获取所有stuchoosecourse的ids

String  nativeSql = "select id from tableName ";

List list = commonEao.executeGetNativeSQL(nativeSql);

//将list中的id放到HashSet中

HashSet dbSet = new HashSet();

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里,暂且不说效率的问题,请问你的内存受得了吗?答案是肯定的,内存会被撑爆。那么,这个问题必须解决。于是,最终的版本如下:

public String findDeletedStuChooseCourseIds(List stuChooseCourseIds,String schoolCalendarId) {

List delIds = new ArrayList();

//获取所有stuchoosecourse的ids

String  nativeSql = "select id from tableName where schoolcalendarid='"+schoolCalendarId+"'";

List list = commonEao.executeGetNativeSQL(nativeSql);

//将list中的id放到HashSet中

HashSet dbSet = new HashSet();

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);

}

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

通过这次的优化,让我真正感受到了数据结构的魅力。骚年,有时间好好学习一下数据结构吧! 本文网址:http://www.shaoqun.com/a/94029.html

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:admin@shaoqun.com。

0

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值