两个for循环嵌套优化

背景

前段时间在公众号中看到一篇技术文章,关于for循环嵌套的优化方法,感觉很实用(比较原来自己遇到过),下面分享给大家,同时加深理解,欢迎讨论。
数量较小时,嵌套for循环运行基本没什么影响,如果数据量较大运行时间明显变长,毕竟复杂度是O(n),数据量大或者循环嵌套过多,代码执行耗时会很恐怖。

优化方式

优化方式一

在for循环中使用break,减少执行次数,从而减少耗时,当然也是针对数据量不大,嵌套少,有一定的判断条件。
如下代码

public static List<User> getUserTestList() {
    List<User> users = new ArrayList<>();
    for (int i = 1; i <= 50000; i++) {
        User user = new User();
        user.setName(UUID.randomUUID().toString());
        user.setUserId((long) i);
        users.add(user);
    }
    return users;
}

public static List<UserMemo> getUserMemoTestList() {
    List<UserMemo> userMemos = new ArrayList<>();
    for (int i = 30000; i >= 1; i--) {
        UserMemo userMemo = new UserMemo();
        userMemo.setContent(UUID.randomUUID().toString());
        userMemo.setUserId((long) i);
        userMemos.add(userMemo);
    }
    return userMemos;
}
public static void main(String[] args) {
    List<User> userTestList = getUserTestList();
    List<UserMemo> userMemoTestList = getUserMemoTestList();


    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    for (User user : userTestList) {
        Long userId = user.getUserId();
        for (UserMemo userMemo : userMemoTestList) {
            if (userId.equals(userMemo.getUserId())) {
                String content = userMemo.getContent();
                System.out.println("模拟数据content 业务处理......"+content);
                break;
            }
        }
    }


    stopWatch.stop();
    System.out.println("最终耗时"+stopWatch.getTotalTimeMillis());


}

耗时比两个for循环执行时间缩短一半以上。

优化方式二

使用map 去优化,map的取值效率 在多数的情况下是能维持接近 O(1) 的 ,数组加链表。
相当于拿到userId 想去开盲盒的时候, 根据userId 这个key hash完能直接找到数组里面的索引标记位, 如果底下没链表(有的话O(logN)),直接取出来就完事了。
示例代码如下:

public static void main(String[] args) {
    List<User> userTestList = getUserTestList();
    List<UserMemo> userMemoTestList = getUserMemoTestList();


    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    Map<Long, String> contentMap =
            userMemoTestList.stream().collect(Collectors.toMap(UserMemo::getUserId, UserMemo::getContent));

    for (User user : userTestList) {
        Long userId = user.getUserId();
        String content = contentMap.get(userId);

        if (StringUtils.hasLength(content)) {
            System.out.println("模拟数据content 业务处理......" + content);
        }

    }

    stopWatch.stop();
    System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());


}

运行结果耗时不到1秒。

特别感谢“java基基”、“芋道源码”公众号提供的相关文章,感谢分享资料的作者。

【腾讯云】11.11云上盛惠,云服务器首年1.8折起,买1年送3个月!境外云服务器15元/月起,买更多省更多!
https://cloud.tencent.com/act/cps/redirect?redirect=5559&cps_key=3e0f3ba5c4cc727403e88457eb5c4914&from=console

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值