Java中 替换 嵌套for循环的 高效率方式。

发布时间:2018-08-12作者:laosun阅读(6685)

Java中

    前几天有人问过我一个问题,就是两个嵌套for循环执行效率的问题,问有什么好的办法替换。当时我想了想,实在想不起来,哎,惭愧!!! 请教了答案,恍然大悟。

    比如:两个list中分别装有相同的对象数据。 list1中有3万条对象数据。 list2中有2万条对象数据(但是对象中的某个属性变量为空)。两个list中的id或者其他变量都一模一样。请用最快的方式找出list2中变量为空的那个对象,并且去list1中找出id相同的对象。 或者可以理解成,从list2中找出变量为空的,去list1中找出对应的对象,然后把为空的列补上。总之就是这么一个意思,先 for 循环 list2,判断一下每个对象的那个属性变量是否为空,如果为空,再去for循环list1,找出id一样的对象,就算执行成功了。

    那么请看下边的for循环嵌套的解决方式:

    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 值为空!!!");
                }
            }
        }
    }

    这样真的好吗? 如果有上万,甚至十几万的数据,那么这个执行效率问题,我就不多说了。 非常非常的慢。

    下边来看使用map代替的执行方式,以及两种方式的效率对比:

    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),"技术客",(i+1), date));
    			if(i%2==0){
    				list2.add(new Member((i+1),null,(i+1), date));
    			}
    		}
    		
    		//双for循环嵌套测试
    		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循环查询时间为:"+(s2-s1)+"(毫秒),一共查询出"+forNumber+"条数据 \n\n\n");
    		TimeUnit.SECONDS.sleep(3);
    		
    		//map查询测试
    		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结构查询时间为:"+(s4-s3)+"(毫秒),一共查询出"+mapNumber+"条数据 \n\n\n");
    	}
    
    }

    输出结果:

    双for循环查询时间为:1578(毫秒),一共查询出15000条数据 
    
    
    
    使用map结构查询时间为:14(毫秒),一共查询出15000条数据


    如果我们模拟10万条数据,然后其中五千条重复数据的情况下:效率更是天壤之别。

    看输出结果:

    双for循环查询时间为:30929(毫秒),一共查询出50000条数据 
    
    
    
    使用map结构查询时间为:24(毫秒),一共查询出50000条数据

    循环数据越小,两者差别也就越小,但是数据量越大,差别也就越大。 10万条数据的差别竟然达到上千倍!

9 +1

版权声明

 Java  源码  扩展

 请文明留言

5 条评论