ArrayList集合中contains方法底层代码分析

在ArrayList类集合中很常用的方法之一就是contains()方法,它可以判断一个集合中是否含有指定元素,知其然更要知其所以然,知道了它的作用后为了以后能更好的使用它,我们以举几个示例来来分析一下底层代码。

1.第一个示例

package contains;

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		ArrayList<String> list=new ArrayList();
		list.add("Tom");
		System.out.println(list.contains("Tom"));
	}
}

按住Ctrl键点击contains方法进入底层代码查看到如下源代码:

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
   
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

第1行:当list调用contains方法时,传入变量name,用Object类型o存放String类对象name,所以这是一个对象上转型的过程

第2行:返回值时调用了下面的indexOf方法。

第5行:调用该方法时将上一个方法中的Object类型变量o传入该方法中,此时该方法中的o还是一个指向String类型对象name的上转型对象。

第6行:判断该上转型对象是否为null,该例中name显然不为null,所以返回值为false,执行else代码块。

第11行:进入for循环遍历集合中的元素,遍历次数就是集合中元素的个数。

第12行:该处的使用是一个多态,表层上调用的是Object类中的equals方法,实则调用的是String类中的equals方法,将指向的对象name与遍历出来的集合中的每一个元素进行比较,该例中当遍历到第一个元素时即返回true进入if代码块返回true然后结束方法。

2.第二个示例

该例中将contains方法中传入的参数name变成null:

package contains;

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		ArrayList<String> list=new ArrayList();
		list.add("Tom");
		String name=null;
		System.out.println(list.contains(name));
	}
}

这时我们再来分析一下底层代码:

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
   
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

第1行:当list调用contains方法时,传入变量name,用Object类型o存放String类对象name,所以这是一个对象上转型的过程

第2行:返回值时调用了下面的indexOf方法。

第5行:调用该方法时将上一个方法中的Object类型变量o传入该方法中,此时该方法中的o还是一个指向String类型对象name的上转型对象。

第6行:判断该上转型对象是否为null,该例中name变成了null,所以返回值为true,执行if代码块。

第7行:进入for循环遍历集合中的元素,遍历次数就是集合中元素的个数。

第8行:该语句对集合中遍历的每一个元素判断是否为null,该例中集合中没有null元素,所以这里并没有进入if代码块,跳出了for循环,返回了-1。

3.第三个示例

该例中创建了一个Test类对象test,调用contains方法时将test传入方法,这时我们再来分析一下底层代码的执行情况:

package contains;

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		ArrayList<String> list=new ArrayList();
		list.add("Tom");
		Test test=new Test();
		System.out.println(list.contains(test));
	}
}

 还是分析下面这段底层代码:

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
   
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

第1行:当list调用contains方法时,传入变量test,用Object类型o存放Test类对象test,所以这是一个对象上转型的过程

第2行:返回值时调用了下面的indexOf方法。

第5行:调用该方法时将上一个方法中的Object类型变量o传入该方法中,此时该方法中的o还是一个指向Test类型对象test的上转型对象。

第6行:判断该上转型对象是否为null,该例中test中存的是堆中的地址,不为空,所以返回值为false,执行else代码块。

第11行:进入for循环遍历集合中的元素,遍历次数就是集合中元素的个数。

第12行:该处正常来说应该是一个多态的调用,因为Object类中指向的是Test类的对象test,所以表层调用Object类的方法实则应该调用Test类中的equals方法,但是Test类中并没有equals方法,所以调用的相当于还是Object类中的equals方法。

下面是Object类中equals方法的源代码:

    public boolean equals(Object obj) {
        return (this == obj);
    }

可以看出,该方法仅仅是判断二者的地址是否相同,由于二者不是同一类,所以在集合中一定没有同样地址的元素,一定不会执行到该if代码块。

第15行:最后返回-1

四.思考:

第三个示例是由于Test类中没有重写equals方法,所以调用的Object类中的equals方法,那么如果我们在Test类中重写一个equals方法,那就意味着可以调用自己重写的方法:

package contains;

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		ArrayList<String> list=new ArrayList();
		list.add("Tom");
		Test test=new Test();
		System.out.println(list.contains(test));
	}

	@Override
	public boolean equals(Object obj) {
		System.out.println("111");
		return super.equals(obj);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值