前言 最近又是一轮代码review , 发现了一些实现去重的代码,在使用 lsit.contain ......
如:
我沉思,是不是其实很多初学者也存在这种去重使用问题?
所以我选择把这个事情整出来,分享一下。
基于 spring boot + mybatis plus + vue & element 实现的后台管理系统 + 用户小程序,支持 rbac 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/yunaiv/ruoyi-vue-pro 视频教程:https://doc.iocoder.cn/video/ 正文 首先是造出一个 list 模拟数据,一共2w条,里面有一半数据1w条是重复的:
public static list gettestlist() { list list = new arraylist(); for (int i = 1; i = 1; i--) { list.add(string.valueof(i)); } return list;} 先看看 我们用contain 去重的 代码:
/** * 使用 list.contain 去重 * * @param testlist */private static void usecontain2distinct(list testlist) { system.out.println(contains 开始去重,条数: + testlist.size()); list testlistdistinctresult = new arraylist(); for (string str : testlist) { if (!testlistdistinctresult.contains(str)) { testlistdistinctresult.add(str); } } system.out.println(contains 去重完毕,条数: + testlistdistinctresult.size());} 我们调用一下看看耗时:
public static void main(string[] args) { list testlist = gettestlist(); stopwatch stopwatch = new stopwatch(); stopwatch.start(); usecontaindistinct(testlist); stopwatch.stop(); system.out.println(去重 最终耗时 + stopwatch.gettotaltimemillis());} 耗时:
评价:list.contain 的效率,我的建议是,知道就行,别用。
众所周知set 不存在 重复数据, 所以我们来看看 使用hashset去重的性能:
ps:这里是采取使用 set的add 方法做去重
/** * 使用set去重 * * @param testlist */private static void usesetdistinct(list testlist) { system.out.println(hashset.add 开始去重,条数: + testlist.size()); list testlistdistinctresult = new arraylist(new hashset(testlist)); system.out.println(hashset.add 去重完毕,条数: + testlistdistinctresult.size());} 我们调用一下看看耗时:
public static void main(string[] args) { list testlist = gettestlist(); stopwatch stopwatch = new stopwatch(); stopwatch.start(); usesetdistinct(testlist); stopwatch.stop(); system.out.println(去重 最终耗时 + stopwatch.gettotaltimemillis());} 耗时:
评价:hashset 的效率,我的建议是,推荐。
为什么耗时 差距这么大? 不多说,我们看源码:
list.contains(o):
可以看到里面用到了 index(o) :
时间复杂度 :o(n) ,n: 元素个数
那么我们看看 set.add(o) 是怎么样的 :
map的add , 老生常谈就不谈了,hash完 直接塞到某个位置, 时间复杂度 : o(1) 。
所以 o(n) 和 o(1) 谁快 谁慢 ?显然。
ps:顺嘴说下 hashset的 contain
时间复杂度也是 :o(1)
那么我们最后再看看别的去重:
双for循环 ,remove去重
/** * 使用双for循环去重 * @param testlist */private static void use2fordistinct(list testlist) { system.out.println(list 双循环 开始去重,条数: + testlist.size()); for (int i = 0; i < testlist.size(); i++) { for (int j = i + 1; j < testlist.size(); j++) { if (testlist.get(i).equals(testlist.get(j))) { testlist.remove(j); } } } system.out.println(list 双循环 去重完毕,条数: + testlist.size());}public static void main(string[] args) { list testlist = gettestlist(); stopwatch stopwatch = new stopwatch(); stopwatch.start(); use2fordistinct(testlist); stopwatch.stop(); system.out.println(去重 最终耗时 + stopwatch.gettotaltimemillis());} 耗时:
评价:知道就行,图个乐,别用,贼慢,而且代码看起来乱:。
stream的distinct去重:
/** * 使用stream 去重 * * @param testlist */private static void usestreamdistinct(list testlist) { system.out.println(stream 开始去重,条数: + testlist.size()); list testlistdistinctresult = testlist.stream().distinct().collect(collectors.tolist()); system.out.println(stream 去重完毕,条数: + testlistdistinctresult.size());}public static void main(string[] args) { list testlist = gettestlist(); stopwatch stopwatch = new stopwatch(); stopwatch.start(); usestreamdistinct(testlist); stopwatch.stop(); system.out.println(去重 最终耗时 + stopwatch.gettotaltimemillis());} 耗时:
评价:还不错,主要是代码也蛮简洁,有一点点动心。
好了,该篇就到这。
最新调查:95%的人会为微信放弃苹果,改用安卓手机
基于发射分集的空时码及其应用
晶振没坏但不起振 PCB板上的晶体不起振为啥?
降压变换器,降压变换器输入输出电压关系公式
什么是光纤无源器件技术
不好意思,list.contain 去重该换换了!
STM32串口通信详解
如何让RTOS多任务访问同一个UART?
双曲面“王者”!小米Note2真机实拍 组图
荣耀V8配VR 手机厂卡位虚拟现实是跟风还是布局?
基于MSP430单片机和CS8900A的以太网终端模块电路
NVIDIA斥怒:显卡都落在了矿工手中 游戏玩家一卡难求
索尼Xperia1 III详细规格配置曝光
一文看懂贴片绕线屏蔽电感感值不稳定的解决方法
小米RedmiNote7评测 很多方面远远超过了千元机的配置相当的优秀
ADC0809引脚图与接口电路的详细资料说明
理想汽车首次在国内造车新势力中率先盈利
相位噪声的两种定义与测试方法简述
黄梅天,衣服晾不干怎么办?
如何在Ubuntu16.04上安装并使用 ensorFlow