Java優(yōu)化for循環(huán)嵌套的高效率方法
前幾天有人問(wèn)過(guò)我一個(gè)問(wèn)題,就是兩個(gè)嵌套for循環(huán)執(zhí)行效率的問(wèn)題,問(wèn)有什么好的辦法替換。當(dāng)時(shí)我想了想,實(shí)在想不起來(lái),哎,慚愧?。?! 請(qǐng)教了答案,恍然大悟。
比如:兩個(gè)list中分別裝有相同的對(duì)象數(shù)據(jù)。 list1中有3萬(wàn)條對(duì)象數(shù)據(jù)。 list2中有2萬(wàn)條對(duì)象數(shù)據(jù)(但是對(duì)象中的某個(gè)屬性變量為空)。兩個(gè)list中的id或者其他變量都一模一樣。請(qǐng)用最快的方式找出list2中變量為空的那個(gè)對(duì)象,并且去list1中找出id相同的對(duì)象。 或者可以理解成,從list2中找出變量為空的,去list1中找出對(duì)應(yīng)的對(duì)象,然后把為空的列補(bǔ)上??傊褪沁@么一個(gè)意思,先 for 循環(huán) list2,判斷一下每個(gè)對(duì)象的那個(gè)屬性變量是否為空,如果為空,再去for循環(huán)list1,找出id一樣的對(duì)象,就算執(zhí)行成功了。
那么請(qǐng)看下邊的for循環(huán)嵌套的解決方式:
for(Member m2:list2){
if(m2.getName()==null){
for(Member m1:list1){
if(m1.getId().intValue()==m2.getId().intValue()){
System.out.println(m2.getId()+" Name 值為空!!!");
}
}
}
}
這樣真的好嗎? 如果有上萬(wàn),甚至十幾萬(wàn)的數(shù)據(jù),那么這個(gè)執(zhí)行效率問(wèn)題,我就不多說(shuō)了。 非常非常的慢。
下邊來(lái)看使用map代替的執(zhí)行方式,以及兩種方式的效率對(duì)比:
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
class Member {
private Integer id;
private String name;
private Integer age;
private Date addDate;
public Member() {
}
public Member(Integer id, String name, Integer age, Date addDate) {
super();
this.id = id;
this.name = name;
this.age = age;
this.addDate = addDate;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getAddDate() {
return addDate;
}
public void setAddDate(Date addDate) {
this.addDate = addDate;
}
}
public class For2 {
public static void main(String[] args) throws InterruptedException {
List<Member> list1 = new ArrayList<>();
List<Member> list2 = new ArrayList<>();
for(int i=0;i<30000;i++){
Date date = new Date();
list1.add(new Member((i+1),"技術(shù)客",(i+1), date));
if(i%2==0){
list2.add(new Member((i+1),null,(i+1), date));
}
}
//雙for循環(huán)嵌套測(cè)試
long s1 = System.currentTimeMillis();
int forNumber = 0;
for(Member m2:list2){
if(m2.getName()==null){
for(Member m1:list1){
if(m1.getId().intValue()==m2.getId().intValue()){
// System.out.println(m2.getId()+" Name 值為空!!!");
forNumber++;
}
}
}
}
long s2 = System.currentTimeMillis();
System.out.println("雙for循環(huán)查詢(xún)時(shí)間為:"+(s2-s1)+"(毫秒),一共查詢(xún)出"+forNumber+"條數(shù)據(jù) \n\n\n");
TimeUnit.SECONDS.sleep(3);
//map查詢(xún)測(cè)試
long s3 = System.currentTimeMillis();
int mapNumber = 0;
Map<Integer, Member> map = new HashMap<>();
for(Member m1:list1){
map.put(m1.getId(), m1);
}
for(Member m2:list2){
if(m2.getName()==null){
Member m = map.get(m2.getId());
if(m!=null){
// System.out.println(m2.getId()+" Name 值為空!!!");
mapNumber++;
}
}
}
long s4 = System.currentTimeMillis();
System.out.println("使用map結(jié)構(gòu)查詢(xún)時(shí)間為:"+(s4-s3)+"(毫秒),一共查詢(xún)出"+mapNumber+"條數(shù)據(jù) \n\n\n");
}
}
輸出結(jié)果:
雙for循環(huán)查詢(xún)時(shí)間為:1578(毫秒),一共查詢(xún)出15000條數(shù)據(jù)
使用map結(jié)構(gòu)查詢(xún)時(shí)間為:14(毫秒),一共查詢(xún)出15000條數(shù)據(jù)
如果我們模擬10萬(wàn)條數(shù)據(jù),然后其中五千條重復(fù)數(shù)據(jù)的情況下:效率更是天壤之別。
看輸出結(jié)果:
雙for循環(huán)查詢(xún)時(shí)間為:30929(毫秒),一共查詢(xún)出50000條數(shù)據(jù)
使用map結(jié)構(gòu)查詢(xún)時(shí)間為:24(毫秒),一共查詢(xún)出50000條數(shù)據(jù)
循環(huán)數(shù)據(jù)越小,兩者差別也就越小,但是數(shù)據(jù)量越大,差別也就越大。 10萬(wàn)條數(shù)據(jù)的差別竟然達(dá)到上千倍!
以上就是Java優(yōu)化for循環(huán)嵌套的高效率方法的詳細(xì)內(nèi)容,更多關(guān)于Java 優(yōu)化 for循環(huán)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot?filter配置多個(gè)時(shí),執(zhí)行順序問(wèn)題
這篇文章主要介紹了springboot?filter配置多個(gè)時(shí),執(zhí)行順序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
springboot整合swagger3和knife4j的詳細(xì)過(guò)程
knife4j的前身是swagger-bootstrap-ui,取名knife4j是希望她能像一把匕首一樣小巧,輕量,并且功能強(qiáng)悍,下面這篇文章主要介紹了springboot整合swagger3和knife4j的詳細(xì)過(guò)程,需要的朋友可以參考下2022-11-11
JavaCV與FFmpeg音視頻流處理技巧總結(jié)大全
JavaCV是一個(gè)開(kāi)源的Java接口,它為幾個(gè)著名的計(jì)算機(jī)視覺(jué)庫(kù)(如OpenCV、FFmpeg)提供了Java封裝,這篇文章主要給大家介紹了關(guān)于JavaCV與FFmpeg音視頻流處理技巧總結(jié)的相關(guān)資料,需要的朋友可以參考下2024-05-05
通過(guò)Java計(jì)算文件的MD5值實(shí)現(xiàn)方式
本文將詳細(xì)介紹如何使用Java語(yǔ)言來(lái)計(jì)算文件的MD5值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
MyBatis-Plus中Service接口的lambdaUpdate用法及實(shí)例分析
本文將詳細(xì)講解MyBatis-Plus中的lambdaUpdate用法,并提供豐富的案例來(lái)幫助讀者更好地理解和應(yīng)用該特性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
Spring Boot 整合 TKMybatis 二次簡(jiǎn)化持久層代碼的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot 整合 TKMybatis 二次簡(jiǎn)化持久層代碼的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
java datetime數(shù)據(jù)類(lèi)型去掉時(shí)分秒的案例詳解
在Java中,如果我們想要表示一個(gè)日期而不包括時(shí)間(時(shí)分秒),我們通常會(huì)使用java.time包中的LocalDate類(lèi),這篇文章主要介紹了java datetime數(shù)據(jù)類(lèi)型去掉時(shí)分秒,需要的朋友可以參考下2024-06-06
從Myeclipse 導(dǎo)入到eclipse中無(wú)法識(shí)別為 web項(xiàng)目 問(wèn)題的解決步驟
這篇文章主要介紹了從Myeclipse 導(dǎo)入到eclipse中無(wú)法識(shí)別為 web項(xiàng)目 問(wèn)題的解決步驟,需要的朋友可以參考下2018-05-05

