资讯专栏INFORMATION COLUMN

java性能优化笔记 —— for循环

pkhope / 1044人阅读

摘要:异常捕获在内部捕获异常耗时优化后在外部捕获异常耗时结论捕获异常是很耗资源的,所以不要讲放到循环内部。

1.多层嵌套循环

</>复制代码

  1. stratTime = System.nanoTime();
  2. for (int i = 0; i <10000 ; i++) {
  3. for (int j = 0; j < 100; j++) {
  4. for (int k = 0; k < 10; k++) {
  5. testFunction(i, j, k);
  6. }
  7. }
  8. }
  9. System.out.println("外大内小耗时:"+ (endTime - stratTime));

优化后:

</>复制代码

  1. stratTime = System.nanoTime();
  2. for (int i = 0; i <10 ; i++) {
  3. for (int j = 0; j < 100; j++) {
  4. for (int k = 0; k < 10000; k++) {
  5. testFunction(i, j, k);
  6. }
  7. }
  8. }
  9. endTime = System.nanoTime();
  10. System.out.println("外小内大耗时:"+(endTime - stratTime));

两者耗时对比:

</>复制代码

  1. 外大内小耗时:1582127649
  2. 外小内大耗时:761666633
优化原理

我们先分析原代码循环变量在实例化、初始化、比较、自增等方面的耗时情况:

优化前:

变量 实例化(次数) 初始化(次数) 比较(次数) 自增(次数)
i 1 1 10000 10000
j 10000 10000 10000*100 10000*100
k 10000*100 10000*100 1000010010 1000010010

优化后:

变量 实例化(次数) 初始化(次数) 比较(次数) 自增(次数)
i 1 1 10 10
j 10 10 10*100 10*100
k 10*100 10*100 1010010000 1010010000
结论

嵌套循环应该遵循“外小内大”的原则

2.循环变量的实例化应放在循环外

在1.中优化后的代码基础上,进行二次优化:

</>复制代码

  1. stratTime = System.nanoTime();
  2. int i, j, k;
  3. for (i = 0; i <10 ; i++) {
  4. for (j = 0; j < 100; j++) {
  5. for (k = 0; k < 10000; k++) {
  6. testFunction(i, j, k);
  7. }
  8. }
  9. }
  10. endTime = System.nanoTime();
  11. System.out.println("提取出循环内变量后耗时:"+(endTime - stratTime));

结果如下:

</>复制代码

  1. 外小内大耗时:761666633
  2. 提取出循环内变量后耗时:748479323

优化并不明显,但是当循环越大时,耗时会差距更大

## 优化原理
优化后:

变量 实例化(次数) 初始化(次数) 比较(次数) 自增(次数)
i 1 1 10 10
j 1 10 10*100 10*100
k 1 10*100 1010010000 1010010000
结论

循环变量的实例化应该尽量放在循环外进行

3.提取与循环无关的表达式

</>复制代码

  1. stratTime = System.nanoTime();
  2. for (int i = 0; i < 10000000; i++) {
  3. i=i*a*b;
  4. }
  5. endTime = System.nanoTime();
  6. System.out.println("未提取耗时:"+(endTime - stratTime));

优化后:

</>复制代码

  1. stratTime = System.nanoTime();
  2. c = a*b;
  3. for (int i = 0; i < 10000000; i++) {
  4. i=i*c;
  5. }
  6. endTime = System.nanoTime();
  7. System.out.println("已提取耗时:"+(endTime - stratTime));
结论:

代码中a+b与我们的循环无关,所以应该把它放到外面,避免重复计算。

4.消除循环终止判断时的方法调用

</>复制代码

  1. stratTime = System.nanoTime();
  2. for (int i = 0; i < list.size(); i++) {
  3. }
  4. endTime = System.nanoTime();
  5. System.out.println("未优化list耗时:"+(endTime - stratTime));

优化后:

</>复制代码

  1. stratTime = System.nanoTime();
  2. int size = list.size();
  3. for (int i = 0; i < size; i++) {
  4. }
  5. endTime = System.nanoTime();
  6. System.out.println("优化list耗时:"+(endTime - stratTime));
结论

list.size()每次循环都会被执行一次,这无疑会影响程序的性能,所以应该将其放到循环外面,用一个变量来代替。

5.异常捕获

</>复制代码

  1. stratTime = System.nanoTime();
  2. for (int i = 0; i < 10000000; i++) {
  3. try {
  4. } catch (Exception e) {
  5. }
  6. }
  7. endTime = System.nanoTime();
  8. System.out.println("在内部捕获异常耗时:"+(endTime - stratTime));

优化后:

</>复制代码

  1. stratTime = System.nanoTime();
  2. try {
  3. for (int i = 0; i < 10000000; i++) {
  4. }
  5. } catch (Exception e) {
  6. }
  7. endTime = System.nanoTime();
  8. System.out.println("在外部捕获异常耗时:"+(endTime - stratTime));
结论

捕获异常是很耗资源的,所以不要讲try catch放到循环内部。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68134.html

相关文章

  • 程序员笔记|如何编写高性能Java代码

    摘要:常见标高线程上下文切换频繁线程太多锁竞争激烈标高如果的占用很高,排查涉及到的程序,比如把改造成。抖动问题原因字节码转为机器码需要占用时间片,大量的在执行字节码时,导致长期处于高位现象,占用率最高解决办法保证编译线程的占比。 一、并发 Unable to create new native thread …… 问题1:Java中创建一个线程消耗多少内存? 每个线程有独自的栈内存,共享堆内...

    ky0ncheng 评论0 收藏0
  • 读书笔记(03) - 性能 - JavaScript高级程序设计

    摘要:作用域链查找作用域链的查找是逐层向上查找。而全局变量和闭包则会与之相反,继续保存,所以使用用后需手动标记清除,以免造成内存泄漏。获取元素的属性获取元素的属性等参考文档高级程序设计作者以乐之名本文原创,有不当的地方欢迎指出。 showImg(https://segmentfault.com/img/bVburXV?w=500&h=399); 作用域链查找 作用域链的查找是逐层向上查找。查...

    warnerwu 评论0 收藏0
  • JS性能优化笔记

    摘要:四如果需要遍历数组,应该先缓存数组长度,将数组长度放入局部变量中,避免多次查询数组长度。五尽量选用局部变量而不是全局变量。所以如果这样的表达式重复出现,只要可能,应该尽量少出现这样的表达式,可以利用局部变量,把它放入一个临时的地方进行查询。 通过网上查找资料了解关于性能优化方面的内容,现简单整理,仅供大家在优化的过程中参考使用,如有什么问题请及时提出,再做出相应的补充修改。 一、 让...

    baoxl 评论0 收藏0
  • java笔记

    摘要:没有被引用和没有被使用是两码事。对这一段代码如何做出优化尽量的在里面少创建对象。那么这一万条数据循环然后反序列化变成,性能就回很低。 1.没有被引用和没有被使用是两码事。 javapublic List getConcernListByUserId(String userId) { List myBlackLists= this.getMyBlackListByUse...

    xi4oh4o 评论0 收藏0
  • Java8实战》-读书笔记第一章(02)

    摘要:实战读书笔记第一章从方法传递到接着上次的,继续来了解一下,如果继续简化代码。去掉并且生成的数字是万,所消耗的时间循序流并行流至于为什么有时候并行流效率比循序流还低,这个以后的文章会解释。 《Java8实战》-读书笔记第一章(02) 从方法传递到Lambda 接着上次的Predicate,继续来了解一下,如果继续简化代码。 把方法作为值来传递虽然很有用,但是要是有很多类似与isHeavy...

    lushan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<