使用Map优化双层For循环

笔者在《for循环实战性能优化》中提出了五种提升for循环性能的优化策略,这次我们在其中嵌套循环优化小循环驱动大循环的基础上,借助Map高效的查询性能来优化双层for循环。

如果小循环和大循环的集合元素数量分别为M和N,则双层For循环的循环次数是M*N,随着M和N的增长,对性能的影响越来越大。因此,本文考虑进一步优化。利用下面的代码来模拟测试两种情况的性能:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ForUpdate {

    public static void main(String[] args) {

//        for (int i = 0; i < 10000; i += 10) {
//            loopGivenNum(i);
//        }
        for (int i = 10000; i < 100000; i += 10000) {
            loopGivenNum(i);
        }
        System.out.println("----- done -----");

    }

    private static void loopGivenNum(int i) {
        List<String> smallLoop = getLoopList(i);
        List<String> bigLoop = getLoopList(2 * i);
        long doByForTimes = doByFor(bigLoop, smallLoop);
        long doByMapTimes = doByMap(bigLoop, smallLoop);
        System.out.println("size " + i + ": " + doByForTimes + "," + doByMapTimes);
    }

    /**
     * 获取循环变量
     * @param size 循环变量元素个数
     */
    private static List<String> getLoopList(int size) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            list.add(String.valueOf(i));
        }
        return list;
    }

    private static long doByFor(List<String> bigLoop, List<String> smallLoop) {
        long startTime = System.currentTimeMillis();
        for (String str1 : smallLoop) {
            for (String str2 : bigLoop) {
                if (str1.equals(str2)) {
                    continue;
                }
            }
        }
        return System.currentTimeMillis() - startTime;
    }

    /**
     * 使用 Map 优化
     * @param bigLoop
     * @param smallLoop
     */
    private static long doByMap(List<String> bigLoop, List<String> smallLoop) {
        long startTime = System.currentTimeMillis();
        // 转换成map
        Map<String, String> loopMap = bigLoop.stream().collect(Collectors.toMap(k -> k, Function.identity()));
        System.out.println(loopMap.size());
        for (String str1 : smallLoop) {
            if (loopMap.containsKey(str1)) {
                continue;
            }
        }
        return System.currentTimeMillis() - startTime;
    }
}

输出结果:

size 10000: 756,97
size 20000: 3091,8
size 30000: 4342,7
size 40000: 8848,7
size 50000: 16317,7
size 60000: 31652,7
size 70000: 37078,7

由此可见,数据量越大嵌套For循环执行时间越长,而使用Map后,纵使数据量增长到了20w,执行时间也维持在7ms左右。数据量小的时候,执行结果就不再贴出来了。

结论:使用Map优化后的方法执行的效率比嵌套循环提高了很多很多。

Reference

https://www.cnblogs.com/syui-terra/p/10163117.html

原文地址:https://www.cnblogs.com/east7/p/11985671.html

时间: 2024-11-10 18:00:20

使用Map优化双层For循环的相关文章

论使用HashMap优化双层For循环的实际性能

当需要对两个集合进行相互操作的时候,一般需要进行双层For循环,但我们知道双层For在数量越大的时候性能影响越大 这时候我们会想到的其中一种解决方法就是利用Hashmap在查找数据的高效上来优化双层For 我利用下面的代码来模拟测试两种情况的性能: public static void main(String[] args) { for (int i = 0; i < 10000; i += 10) { List<String> loopList1 = getLoopList(i); L

跳出Java当中的一些循环,跳出双层FOR循环

今天写代码写了个双层的for循环,里面还是用来Iterator,大致意思就是在第二个循环中如果符合条件就给跳出整个双层循环. 刚开始,直接使用break.巴拉巴拉的敲了一堆代码,信心满满的就直接运行.等到结果一看,这不是要我要的.哎··看来不扎实呀! 突然来了兴趣,索性就看看一些资料,总结了几种跳出循环的方式: 1.直接跳出循环: for (int i = 0; i < 10; i ++) { if(i == 4) { break; } System.out.println(i); } Syst

C语言优化实例:循环中减少判断

为了让编译器更好地优化循环,应该尽量让循环中减少判断,方法之一是将判断语句整合进表达式.还是这个例子: for (int i = 0; i < 1000*10; i++) { sum += data[i/1000][i%10]; } 假如我们需要加一个判断,只有非负整数才需要作求和运算: for (int i = 0; i < 1000*10; i++) { if (data[i/1000][i%10] >= 0) sum += data[i/1000][i%10]; } 下面将这个判断

【java】itoo项目实战之大数据查询之使用 new map 优化hibernate之级联查询

在我的上一篇博客<[java]itoo项目实战之hibernate 懒加载优化性能>中,我曾提到过学生数据有2万条,查询数据十分的慢,这是让人很受不了的事情,看着页面进度条一直转着圈圈,那种着急的感觉真的没法形容.最开始考虑着使用lazy 来优化,因为前台框架的原因,lazy 优化并没有起到什么左右,后来就想着有select new map 优化.我先来画画关于查询学生的级联树 这个树的意思就是查询学生的时候它的深度是4级. 在没有优化之前,使用的是hibernate的hql 语句:From

高效遍历匹配Json数据与双层for循环遍历Json数据

工作中往往遇到这种情况,保留用户操作痕迹,比如用户选择过得东西,用户进入其它页面再返回来用户选择的的数据还在. 比如:1.购物车列表中勾选某些,点击任意一项,前往详情页,再返回购物车依旧需要呈现勾选状态           2.勾选人员后,前往别的页面,再次返回,人员依旧程勾选状态           3.等等.... 解决方法:1.把用户选择的数据在本地保存一份 2.进入当前页面拿缓存数据和新数据(从后台获取的数据)进行对比,然后进行对比渲染 在做数据比对的时候,可以通过嵌套for循环,一层f

js流程控制语句--利用双层for循环实现九九乘法表和五角星

js中的流程控制语句:顺序结构 分支结构 循环结构 分支结构:1.if语句 --适用于范围性的判断 语法:if(条件){语句}--如果条件成立 就执行语句           if(条件){语句1}else(){语句2} 如果条件成立 执行语句1,否则执行语句2           if(条件){语句1}else if(){语句2}else(){语句3} 2.三元运算符:只适用于比较简单的判断,可以更加简洁 语法:var 结果=条件?A:B 如果条件满足就是A否则就是B 3.switch....

51nod 1094 和为k的连续区间(暴力和map优化)

题目意思: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1094 一整数数列a1, a2, ... , an(有正有负),以及另一个整数k,求一个区间[i, j],(1 <= i <= j <= n),使得a[i] + ... + a[j] = k. Input 第1行:2个数N,K.N为数列的长度.K为需要求的和.(2 <= N <= 10000,-10^9 <= K <= 10^9

Python 三级菜单与优化(一层循环嵌套)

优化的思路是使用单层循环嵌套完成三级菜单,这个优化思路我非常喜欢,我喜欢在编程的时候用最少的东西写出同样的效果,通常这样会绕来绕去,但非常有趣!!! 需求: 1.运行程序输出第一级菜单: 2.选择一级菜单某项,输出二级菜单,同理输出三级菜单: 3.让用户选择是否要退出: 4.有返回上一级菜单的功能: 多层循环嵌套: data = { 'A':{ "Aa":['Aa1','Aa2','Aa3'], "Ab":['Ab1','Ab2','Ab3'], "Ac&

MySQL的JOIN(三):JOIN优化实践之内循环的次数

这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( id INT PRIMARY KEY AUTO_INCREMENT, type INT ); SELECT COUNT(*) FROM t1; +----------+ | COUNT(*) | +----------+ | 10000 | +----------+ CREATE TABLE t2 (