前言
最近又是一輪代碼review , 發(fā)現(xiàn)了一些實現(xiàn)去重的代碼,在使用 lsit.contain ......
如:
我沉思,是不是其實很多初學(xué)者也存在這種去重使用問題?
所以我選擇把這個事情整出來,分享一下。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
正文
首先是造出一個 List
模擬數(shù)據(jù),一共2W條,里面有一半數(shù)據(jù)1W條是重復(fù)的:
publicstaticListgetTestList() {
Listlist=newArrayList<>();
for(inti=1;i<=?10000;i++){
list.add(String.valueOf(i));
}
for(inti=10000;i>=1;i--){
list.add(String.valueOf(i));
}
returnlist;
}
先看看 我們用contain 去重的 代碼:
/**
*使用list.contain去重
*
*@paramtestList
*/
privatestaticvoiduseContain2Distinct(ListtestList) {
System.out.println("contains 開始去重,條數(shù):"+testList.size());
ListtestListDistinctResult=newArrayList<>();
for(Stringstr:testList){
if(!testListDistinctResult.contains(str)){
testListDistinctResult.add(str);
}
}
System.out.println("contains 去重完畢,條數(shù):"+testListDistinctResult.size());
}
我們調(diào)用一下看看耗時:
publicstaticvoidmain(String[]args){
ListtestList=getTestList();
StopWatchstopWatch=newStopWatch();
stopWatch.start();
useContainDistinct(testList);
stopWatch.stop();
System.out.println("去重最終耗時"+stopWatch.getTotalTimeMillis());
}
耗時:
評價:list.contain 的效率,我的建議是,知道就行,別用。
眾所周知Set 不存在 重復(fù)數(shù)據(jù), 所以我們來看看 使用HashSet去重的性能:
ps:這里是采取使用 set的add 方法做去重
/**
*使用set去重
*
*@paramtestList
*/
privatestaticvoiduseSetDistinct(ListtestList) {
System.out.println("HashSet.add 開始去重,條數(shù):"+testList.size());
ListtestListDistinctResult=newArrayList<>(newHashSet(testList));
System.out.println("HashSet.add 去重完畢,條數(shù):"+testListDistinctResult.size());
}
我們調(diào)用一下看看耗時:
publicstaticvoidmain(String[]args){
ListtestList=getTestList();
StopWatchstopWatch=newStopWatch();
stopWatch.start();
useSetDistinct(testList);
stopWatch.stop();
System.out.println("去重最終耗時"+stopWatch.getTotalTimeMillis());
}
耗時:
評價:HashSet 的效率,我的建議是,推薦。
為什么耗時 差距這么大?
不多說,我們看源碼:
list.contains(o)
:
可以看到里面用到了 index(o)
:
時間復(fù)雜度 :O(n)
,n: 元素個數(shù)
那么我們看看 set.add(o)
是怎么樣的 :
map的add , 老生常談就不談了,hash完 直接塞到某個位置, 時間復(fù)雜度 : O(1)
。
所以 O(n)
和 O(1)
誰快 誰慢 ?顯然。
ps:順嘴說下 hashset的 contain
時間復(fù)雜度也是 :O(1)
那么我們最后再看看別的去重:
雙for循環(huán) ,remove去重
/**
*使用雙for循環(huán)去重
*@paramtestList
*/
privatestaticvoiduse2ForDistinct(ListtestList) {
System.out.println("list 雙循環(huán)開始去重,條數(shù):"+testList.size());
for(inti=0;ifor(intj=i+1;jif(testList.get(i).equals(testList.get(j))){
testList.remove(j);
}
}
}
System.out.println("list 雙循環(huán)去重完畢,條數(shù):"+testList.size());
}
publicstaticvoidmain(String[]args){
ListtestList=getTestList();
StopWatchstopWatch=newStopWatch();
stopWatch.start();
use2ForDistinct(testList);
stopWatch.stop();
System.out.println("去重最終耗時"+stopWatch.getTotalTimeMillis());
}
耗時:
評價:知道就行,圖個樂,別用,賊慢,而且代碼看起來亂:。
stream的distinct去重:
/**
*使用Stream去重
*
*@paramtestList
*/
privatestaticvoiduseStreamDistinct(ListtestList) {
System.out.println("stream 開始去重,條數(shù):"+testList.size());
ListtestListDistinctResult=testList.stream().distinct().collect(Collectors.toList());
System.out.println("stream 去重完畢,條數(shù):"+testListDistinctResult.size());
}
publicstaticvoidmain(String[]args){
ListtestList=getTestList();
StopWatchstopWatch=newStopWatch();
stopWatch.start();
useStreamDistinct(testList);
stopWatch.stop();
System.out.println("去重最終耗時"+stopWatch.getTotalTimeMillis());
}
耗時:
評價:還不錯,主要是代碼也蠻簡潔,有一點點動心。
好了,該篇就到這。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7002瀏覽量
88940 -
代碼
+關(guān)注
關(guān)注
30文章
4779瀏覽量
68521 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14338
原文標(biāo)題:不好意思,list.contain 去重該換換了!
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論