【Java】Java中使用HashMap优化多层for循环嵌套以及for循环之性能优化

这篇具有很好参考价值的文章主要介绍了【Java】Java中使用HashMap优化多层for循环嵌套以及for循环之性能优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

for循环是开发时常用的语法之一,比如对数组,集合的遍历等,但是如果使用不好也会出现很多新能损耗的问题,今天就来讲解一下for循环的常用性能优化问题。

for循环 里面还有 for循环, 然后做一些数据匹配、处理 这种场景。

使用HashMap优化多级嵌套循环

m层嵌套的n次的for循环的时间复杂度为O(n^m),如下所示:

优化前

public class forTradition {
 public static void main(String[] args){
 
     List<Student> stus = new ArrayList<>();
     //  为stus写入10条数据 ... 略
     List<Grade> gs = new ArrayList<>();
     //  为gs写入10条数据 ... 略
     
     for (int i = 0 ; i < stus.size() ; i++ ) {
         Student stu = stus.get(i);
         Integer id = stu.getId();
         String stuName = stu.getName();
         for (int j = 0 ; j < gs.size() ; j++ ) {
         	Grade g = gs.get(j);
         	if( id == g.getStuId() ) { 
	            System.out.println( "学生:" + stuName + ",成绩:" + g.getValue() );
         	}
    	 }
 	 }
}

优化后

public class forNew {
 public static void main(String[] args){
 
     List<Student> stus = new ArrayList<>();
     //  为stus写入10条数据 ... 略
     List<Grade> gs = new ArrayList<>();
	 //  为gs写入10条数据 ... 略
	 
	 Map<Integer,Integer> gradesMap = 
	 		gs.stream().collect(Collectors.toMap( data -> data.getStuId() , data -> data.getValue() );
      
     for (int i = 0 ; i < stus.size() ; i++ ) {
         Student stu = stus.get(i);
         Integer value = gradesMap.get(stu.getId());
         if( null != value ) {
         	System.out.println( "学生:" + stu.getName() + ",成绩:" + value );
		 }
	 }
  }
}

for循环之性能优化

嵌套循环

嵌套循环是有俩层或者俩层以上的循环嵌套在一起,下面直接上代码说明。

外大内小嵌套

   /**
     * 大循环驱动小循环(即外大内小)
     */
    private static void bigSmall() {
        long stratTime = System.nanoTime();
        for (int i = 0; i < 10000000; i++) {
            for (int j = 0; j < 100; j++) {

            }
        }
        long endTime = System.nanoTime();
        System.out.println("外大内小耗时:" + (endTime - stratTime));
    }

执行看一下结果耗时:

外大内小耗时:8743800

再看看外小内大耗时情况

外小内大嵌套

   /**
     * 小循环驱动大循环(即外小内大)
     */
    private static void smallBig() {
        long stratTime = System.nanoTime();
        for (int i = 0; i < 100; i++) {
            for (int j = 0; j < 10000000; j++) {

            }
        }
        long endTime = System.nanoTime();
        System.out.println("外小内大耗时:" + (endTime - stratTime));
    }

执行看一下结果耗时:

外小内大耗时:6922600

好了,综合比较一下俩者的执行时间,时差还是很大的。

外小内大耗时:6922600 ;外大内小耗时:8743800

分析总结

由以上对比可知,优化后性能显著提升。嵌套循环应该遵循“外小内大”的原则,虽然循环次数没变,但是耗时却长了很大。这就好比你复制很多个小文件和复制几个大文件的区别,虽然总的大小没变,但是复制大文件明显比多个小文件更快。

循环变量的实例化

把循环变量的实例放在循环内:

/**
 * 循环变量放在循环内
 */
private static void smallBigBetterTwo() {
    long stratTime = System.nanoTime();
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < 10000000; j++) {

        }
    }
    long endTime = System.nanoTime();
    System.out.println("循环内变量耗时:" + (endTime - stratTime));
}

执行耗时:

循环内变量耗时:4934500

把循环变量的实例放在循环之外:

/**

  • 循环变量放在循环外
    */
    private static void smallBigBetter() {
    long stratTime = System.nanoTime();
    int i, j;
    for (i = 0; i < 100; i++) {
    for (j = 0; j < 10000000; j++) {

     }
    

    }
    long endTime = System.nanoTime();
    System.out.println(“循环外变量耗时:” + (endTime - stratTime));
    }

执行耗时:

循环外变量耗时:5013800

对比一下把变量放在循环内和循环外对比耗时,发现时差还是挺大的:

循环内变量耗时:4934500;循环外变量耗时:5013800

分析总结

虽然优化效果并不明显,但是随着循环次数的增加,耗时会越来越大,优化效果则会越来越明显。分析:优化前需要实例化1+i=101次,优化后仅仅2次。总结:循环变量的实例化应放在循环外。

提取与循环无关的表达式

没有提取无关的表达式

   /**
     * 未提取无关的表达式
     */
    private static void calculationInner() {
        int a = 3;
        int b = 7;
        long stratTime = System.nanoTime();
        for (int i = 0; i < 10000000; i++) {
            i = i * a * b;
        }
        long endTime = System.nanoTime();
        System.out.println("未提取耗时:" + (endTime - stratTime));

    }

没有提取耗时:

未提取耗时:800

提取了无关的表达式

/**
 * 提取无关的表达式
 */
private static void calculationOuter() {
    int a = 3;
    int b = 7;
    int c = a * b;
    long stratTime = System.nanoTime();
    for (int i = 0; i < 10000000; i++) {
        i = i * c;
    }
    long endTime = System.nanoTime();
    System.out.println("已提取耗时:" + (endTime - stratTime));
}

提取了无关表达式耗时:

已提取耗时:500

分析总结

代码中a*b与循环无关,所以应该把它放到外面,避免重复计算。从理论角度分析,由于减少了计算次数,故优化后性能会更高。

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

stratTime = System.nanoTime();
for (int i = 0; i < list.size(); i++) { 

}
endTime = System.nanoTime();
System.out.println("未优化list耗时:"+(endTime - stratTime));

耗时:

未优化list耗时:253800

优化后

stratTime = System.nanoTime();
int size = list.size();
for (int i = 0; i < size; i++) { 

}
endTime = System.nanoTime();
System.out.println("优化list耗时:"+(endTime - stratTime));

耗时:

优化list耗时:142500

分析总结

每次循环,list.size()都会被执行一次,这无疑会影响程序的性能,所以应该将其放到循环外面,用一个变量来缓存其size,不要让这一点点代码而消耗我们这么多性能。

异常捕获

在内部捕获异常

/**
     * 在内部捕获异常
     */
    private static void catchInner() {
        long stratTime = System.nanoTime();
        for (int i = 0; i < 10000000; i++) {
            try {
            } catch (Exception e) {
            }
        }
        long endTime = System.nanoTime();
        System.out.println("在内部捕获异常耗时:" + (endTime - stratTime));
    }

执行耗时:

在内部捕获异常耗时:3352700

在外部捕获异常

/**
 * 在外部捕获异常
 */
private static void catchOuter() {
    long stratTime = System.nanoTime();
    try {
        for (int i = 0; i < 10000000; i++) {
        }
    } catch (Exception e) {

    }
    long endTime = System.nanoTime();
    System.out.println("在外部捕获异常耗时:" + (endTime - stratTime));
}

执行耗时:

在外部捕获异常耗时:2893600

分析总结:

捕获异常很占用资源,所以不要把try catch放到循环内部,优化后性能同样有好几个数量级的提升。另外, 《Effective Java》一书指出for-each循环优先于传统的for循环,它在简洁性和预防bug方面有着传统for循环无法媲美的优势,并且,没有性能方面的损失,因此,推荐使用for-each循环。文章来源地址https://www.toymoban.com/news/detail-590233.html

到了这里,关于【Java】Java中使用HashMap优化多层for循环嵌套以及for循环之性能优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python---练习:使用for循环嵌套实现打印九九乘法表

    思考: 外层 循环主要用于控制循环的 行数 , 内层 循环用于控制 列数。 基本语法: 序列1  序列2 ,就可以是range(1, 10)   -----也就是从1,到9。 参考while循环: 相关链接Python---练习:使用while嵌套循环打印 9 x 9乘法表-CSDN博客 最终代码:

    2024年02月08日
    浏览(38)
  • vue - 动态绑定ref(使用变量)以及获取方式,解决v-for循环嵌套自定义子组件时无法this.$refs.xx找到动态组件的情况(详细示例教程)适合 vue.js nuxt.js uniapp

    正常情况,我们需要在vue中获得某个dom或者组件,我们会通过绑定 ref 然后通过绑定后的名字来获取这个dom 。 但是,如果我们在v-for中绑定ref的话,那么这个ref就会存在多个,比如我们点击事件让对应的显示/隐藏的话,我们很难找到这个对应的元素。 那么,这时我们需要动

    2024年02月13日
    浏览(52)
  • python跳出多层for循环

    刷算法题时遇到这样一个题目,我的解法里需要使用到两层for循环,且当第二层for循环里不满足条件时,需要终止第一层for循环 题目描述 已知自然数1,2,…,N(1=N=100)依次入栈,请问序列C1,C2,…,CN是否为合法的出栈序列。 输入 输入包含多组测试数据。 每组测试数据

    2024年02月12日
    浏览(39)
  • python跳出多层for循环的方法

    在业务逻辑中有时候会遇到两层for循环的情况,触发某些条件时,需要直接退出两层for循环 而python官方是没有 goto 语句的那么我们可以这样实现 这段代码什么意思呢 python里面for...else...表示如果这个循环正常的走完了则会执行else里面的代码,异常退出则不会执行,我们对内

    2024年02月05日
    浏览(41)
  • java解析多层嵌套json字符串

    在java 程序中,经常会涉及到各种变量值提取的问题,下面给出简单的示例及说明: JSON实际上也是键值对(\\\"key\\\":\\\"value\\\"),key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null) value如果是字符串,用jsonobj.getString(\\\"key\\\")获取 value如果是数

    2024年02月15日
    浏览(62)
  • Python——for循环的嵌套

      用Python坚持表白一百天,每天都送10朵花,一百天表白成功! 运行代码如下:  

    2024年01月16日
    浏览(40)
  • 微信小程序for循环嵌套

    wx:for-item=“pro” pro 自定义循环体参数

    2024年04月26日
    浏览(37)
  • 44. python的for循环嵌套

    嵌套是指一个对象中包含另一个与它相似的对象。 俄罗斯套娃就是典型的嵌套,一个套娃里有多个外观相同,大小不同的娃。 【Python中的嵌套】 列表嵌套:列表的元素为列表。 if嵌套:if语句中嵌套有一个或多个if语句。 for循环嵌套:for循环语句中嵌套有一个或多个for循环

    2024年02月09日
    浏览(43)
  • 【C语言初学必看】一知半解的for循环嵌套for循环

     初学C语言,常常遇到for循环中嵌套个for循环,初学者对于这种形式总是一知半解,这次我就整理了常见的for循环嵌套for循环的题目,我们一起争取一举拿下这类题。学废他们,以后再见到就不怕啦!每天都要学一点呀。加油,奋斗的我们! 💪💪💪 目录⛳ 🔥🚀前言+目录

    2024年02月02日
    浏览(43)
  • 【Python入门】Python循环语句(for循环的嵌套应用)

    前言 📕作者简介: 热爱跑步的恒川 ,致力于C/C++、Java、Python等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于Python零基础入门系列,本专栏主要内容为Python基础语法、判断、循环语句、函数、函数进阶、数据容器、文件操作、异常模块与包、数据可视化等,

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包